我在 Android Studio 项目中使用 Hilt 作为 DI。我知道“ViewModel 绝不能引用视图、生命周期或任何可能保存对活动上下文的引用的类”。
所以可以发现A图中对于Code A有一条警告信息。
不过ViewModelComponentHilt的已经绑定了Application,你可以看看这篇文章。
1: 我不知道为什么 private val appContext: Application在ViewModel中不显示警告信息,是否意味着我在使用Hilt时可以使用Applicationin ?ViewModel你可以告诉我吗?
2: BTW,private val appContext: Application显示以下信息,为什么?
构造函数参数从不用作属性
代码A
@HiltViewModel
class RecordSoundViewModel @Inject constructor(
@ApplicationContext private val myContext: Context, //Android Studio displays warning information
private val appContext: Application, // Why doesn't it dsiplay warning information
private val savedStateHandle: SavedStateHandle
): ViewModel()
{
...
}
Run Code Online (Sandbox Code Playgroud)
我发现了新的 android 架构组件,我想通过一个小的测试应用程序来测试这对 ViewModel / LiveData。后者有两个片段(在 a 中ViewPager),第一个创建/更新卡片列表(通过 an EditText),第二个显示所有卡片。
我的视图模型:
public class CardsScanListViewModel extends AndroidViewModel {
private MutableLiveData> cardsLiveData = new MutableLiveData();
private HashMap cardsMap = new HashMap();
public CardsScanListViewModel(@NonNull Application application) {
super(application);
}
public MutableLiveData> getCardsLiveData() {
return this.cardsLiveData;
}
public void saveOrUpdateCard(String id) {
if(!cardsMap.containsKey(id)) {
cardsMap.put(id, new Card(id, new AtomicInteger(0)));
}
cardsMap.get(id).getCount().incrementAndGet();
this.cardsLiveData.postValue(cardsMap);
}
}
Run Code Online (Sandbox Code Playgroud)
我的第二个片段:
public class CardsListFragment extends Fragment {
CardsAdapter cardsAdapter;
RecyclerView recyclerCardsList;
public CardsListFragment() {}
@Override
public void …Run Code Online (Sandbox Code Playgroud) android android-fragments rx-android android-livedata android-viewmodel
我有这样的改造服务
public interface BrandsService {
@GET("listBrand")
Call<List<Brand>> getBrands();
}
Run Code Online (Sandbox Code Playgroud)
然后我有一个Repository来从这样的api获取数据
public class BrandsRepository {
public static final String TAG = "BrandsRepository";
MutableLiveData<List<Brand>> mutableLiveData;
Retrofit retrofit;
@Inject
public BrandsRepository(Retrofit retrofit) {
this.retrofit = retrofit;
}
public LiveData<List<Brand>> getListOfBrands() {
// Retrofit retrofit = ApiManager.getAdapter();
final BrandsService brandsService = retrofit.create(BrandsService.class);
Log.d(TAG, "getListOfBrands: 00000000000 "+retrofit);
mutableLiveData = new MutableLiveData<>();
Call<List<Brand>> retrofitCall = brandsService.getBrands();
retrofitCall.enqueue(new Callback<List<Brand>>() {
@Override
public void onResponse(Call<List<Brand>> call, Response<List<Brand>> response) {
mutableLiveData.setValue(response.body());
}
@Override
public void onFailure(Call<List<Brand>> call, Throwable t) …Run Code Online (Sandbox Code Playgroud) android retrofit dagger-2 android-viewmodel android-architecture-components
我正在构建一个使用ArticleBoundaryCallback初始化对API的调用并将响应存储在Room中的应用。我还使用LiveData收听该表,并在PagedListAdapter中显示项目。
问题在于,每次将新数据插入到Room(Article)表中时,整个列表都会刷新。
同样,在配置更改时,似乎再次获取了整个数据(ViewModel不保留它,RecyclerView被重新创建)。
每次插入时,RecyclerView都会跳转(如果插入的是新数据,则跳转几行;如果将新数据替换为旧数据,则跳转到开头)。
整个代码在此GitHub存储库中。
我的课程是:
文章:
@Entity(tableName = "article",
indices={@Index(value="id")})public class Article {
@PrimaryKey(autoGenerate = false)
@SerializedName("_id")
@Expose
@NonNull
private String id;
@SerializedName("web_url")
@Expose
private String webUrl;
@SerializedName("snippet")
@Expose
private String snippet;
@SerializedName("print_page")
@Expose
private String printPage;
@SerializedName("source")
@Expose
private String source;
@SerializedName("multimedia")
@Expose
@Ignore
private List<Multimedium> multimedia = null;
Run Code Online (Sandbox Code Playgroud)
第DAO条:
@Dao
public interface ArticleDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
long insert(Article article);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void update(Article... repos);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertArticles(List<Article> articles);
@Delete
void delete(Article... …Run Code Online (Sandbox Code Playgroud) android-livedata android-viewmodel android-paging mutablelivedata
有关过去的问题如何获取ViewModel?,以及我找到的示例,它不能解决我的情况。我没有在此发表评论的权限,因此我不得不再次询问。我没有要在所有示例和文档中使用的“ of”方法使用的ViewModelProviders类,例如
model = ViewModelProviders.of(this).get(Something.class);
Run Code Online (Sandbox Code Playgroud)
在Android Studio中,我找不到要添加为依赖项的“ android.arch.lifecycle:extensions”。当我搜索时,它说“没什么可显示”。我使用的是API27。因此,尝试使用不推荐使用的元素,我在Fragment中添加了它:
public class EventDetailsFragment extends Fragment
{
EventViewModel viewModel;
@Override
public void onActivityCreated (Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
ViewModelProvider.Factory factory = ViewModelProvider.AndroidViewModelFactory.getInstance(getActivity().getApplication());
// HERE IS THE ISSUE: Seems not good practice to have to create a new ViewModelProvider every time this Fragment is created.
// Perhaps I should just create a singleton ViewModelProvider in the Activity or Application,
// so here could call getActivity().getViewModelProvider(this, factory).
ViewModelProvider viewModelProvider = new ViewModelProvider(this, factory);
viewModel …Run Code Online (Sandbox Code Playgroud) 我目前正在根据官方文档和谷歌提供的示例应用程序(向日葵和 todo-app)将架构组件集成到我的应用程序中。我意识到这些都没有使用ViewModel接口(向日葵应用程序甚至不使用存储库接口)。
我的问题是:省略ViewModels的接口是否合理(包括优点和缺点)?
android design-patterns interface android-viewmodel android-architecture-components
我正在使用LiveData从服务器获取数据并进行观察。我的onChanged()方法只是在第一次调用,而在服务器中的数据更新时不会调用。
用户片段:
UserViewModel userViewModel = ViewModelProviders.of(this).get(UserViewModel.class);
userViewModel.getUser().observe(this, new Observer<User>() {
@Override
public void onChanged(User user) {
//Set UI
}
});
Run Code Online (Sandbox Code Playgroud)
UserViewModel:
public class UserViewModel extends AndroidViewModel {
private LiveData<User> user;
public UserViewModel(Application application) {
super(application);
user = UserRepository.getInstance().fetchUser();
}
public LiveData<User> getUser() {
return user;
}
}
Run Code Online (Sandbox Code Playgroud)
UserRepository:
public class UserRepository {
private ApiService apiService;
private static UserRepository userRepository;
private UserRepository() {
apiService = RestClient.getClient().create(ApiService.class);
}
public synchronized static UserRepository getInstance() {
if (userRepository == null) userRepository = …Run Code Online (Sandbox Code Playgroud) java android android-livedata android-viewmodel android-architecture-components
我正在使用 LiveData 并想了解它可以做什么。我想通过开关用来自不同来源的数据填充我的 RecyclerView(如果你愿意,可以使用过滤器)。
过滤适配器内的值不是一种选择。所以,我决定在我的视图模型中使用MediatorLiveData。
道:
@Query("SELECT * FROM tasks WHERE completed = 0")
LiveData<List<Task>> getActiveTasksLiveData();
@Query("SELECT * FROM tasks")
LiveData<List<Task>> getAllTasksLiveData();
@Query("SELECT * FROM tasks WHERE completed = 1")
LiveData<List<Task>> getClosedTasksLiveData();
Run Code Online (Sandbox Code Playgroud)
回购:
public LiveData<List<Task>> getActiveTasks() {
return mTaskDao.getActiveTasksLiveData();
}
public LiveData<List<Task>> getAllTasks() {
return mTaskDao.getAllTasksLiveData();
}
public LiveData<List<Task>> getClosedTasks() {
return mTaskDao.getClosedTasksLiveData();
}
Run Code Online (Sandbox Code Playgroud)
视图模型
public class MainViewModel extends AndroidViewModel {
private final String TAG = "MainViewModel";
private final AppDataRepository mData;
private MediatorLiveData<List<Task>> mMediatorTasks;
public MainViewModel(@NonNull Application application) …Run Code Online (Sandbox Code Playgroud) android android-recyclerview android-room android-livedata android-viewmodel
当表单中的所有字段都完成时,我想启用 AppCompatButton。
我正在使用 ViewModel 并希望使用数据绑定来启用它。
当视图上的文本更改以更新视图模型中的对象数据时,我有两种方法会触发。
我遇到的问题是当两个字段都完成时,我需要在布局上启用一个按钮以允许它们继续。
一个例子是登录,当用户名和密码字段填满时,登录按钮变为启用。
我目前正在尝试使用savedState 的新Jetpack ViewModel。
implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:1.0.0-rc01'
Run Code Online (Sandbox Code Playgroud)
我正在使用 1 个活动并尝试与 2 个片段共享 1 个 ViewModel,但是当我尝试启动第二个片段时,我从标题中收到错误消息。
这就是我使用savedInstance调用ViewModel的方式:
val repository = (activity?.application as App).getRepository()
viewModel = activity?.run {
ViewModelFactory(repository, this, savedInstanceState).create(MainViewModel::class.java)
} ?: throw Exception("Invalid Activity")
Run Code Online (Sandbox Code Playgroud)
这是我的日志:
java.lang.IllegalArgumentException: SavedStateProvider with the given key is already registered
at androidx.savedstate.SavedStateRegistry.registerSavedStateProvider(SavedStateRegistry.java:111)
at androidx.lifecycle.SavedStateHandleController.attachToLifecycle(SavedStateHandleController.java:50)
at androidx.lifecycle.SavedStateHandleController.create(SavedStateHandleController.java:70)
at androidx.lifecycle.AbstractSavedStateViewModelFactory.create(AbstractSavedStateViewModelFactory.java:67)
at androidx.lifecycle.AbstractSavedStateViewModelFactory.create(AbstractSavedStateViewModelFactory.java:84)
at com.xxx.yyy.presentation.details.DetailsFragment.onCreate(DetailsFragment.kt:29)
at androidx.fragment.app.Fragment.performCreate(Fragment.java:2586)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:838)
at androidx.fragment.app.FragmentTransition.addToFirstInLastOut(FragmentTransition.java:1197)
at androidx.fragment.app.FragmentTransition.calculateFragments(FragmentTransition.java:1080)
at androidx.fragment.app.FragmentTransition.startTransitions(FragmentTransition.java:119)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1866)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824)
at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727)
at androidx.fragment.app.FragmentManagerImpl$2.run(FragmentManagerImpl.java:150)
Run Code Online (Sandbox Code Playgroud)
看起来它正在尝试使用已经注册的 SavedState 并因此出现错误?我认为这就是图书馆的全部意义所在。任何人都可以帮助或指出如何使用此传递参数到 ViewModel 并使用 savedStateHandle?
android android-fragments android-viewmodel android-jetpack androidx
android ×9
android-architecture-components ×3
android-room ×1
androidx ×1
dagger-2 ×1
dagger-hilt ×1
interface ×1
java ×1
retrofit ×1
rx-android ×1