英文:
How to use ViewModel in a fragment?
问题
我正在使用MVVM架构。我有一个活动和几个片段,我想在活动中对API进行请求,然后使用ViewModel根据获取的数据在片段中显示它们。我应该如何做?我当前的解决方案不起作用:
活动:
viewModelRoutesFragment = new ViewModelProvider(this).get(ViewModelRoutesFragment.class);
viewModelRoutesFragment.init();
片段:
viewModelRoutesFragment = new ViewModelProvider(this).get(ViewModelRoutesFragment.class);
viewModelRoutesFragment.getRoutes().observe(getActivity(), new Observer<List<RoutesResponse>>() {
@Override
public void onChanged(List<RoutesResponse> routes) {
//显示数据
}
});
仓库:
public class RemoteRepository {
private ApiRequest apiRequest;
private MutableLiveData<List<RoutesResponse>> routes = new MutableLiveData<>();
public RemoteRepository() {
apiRequest = RetrofitRequest.getInstance().create(ApiRequest.class);
}
public MutableLiveData<List<RoutesResponse>> getRoutes() {
apiRequest.getRoutes()
.enqueue(new Callback<List<RoutesResponse>>() {
@Override
public void onResponse(Call<List<RoutesResponse>> call, Response<List<RoutesResponse>> response) {
if (response.isSuccessful())
routes.setValue(response.body());
}
@Override
public void onFailure(Call<List<RoutesResponse>> call, Throwable t) {
Log.i("Failure", "Fail!");
}
});
return routes;
}
}
ViewModel:
public class ViewModelRoutesFragment extends AndroidViewModel {
private RemoteRepository remoteRepository;
private LiveData<List<RoutesResponse>> routes;
public ViewModelRoutesFragment(@NonNull Application application) {
super(application);
}
public void init() {
remoteRepository = new RemoteRepository();
routes = remoteRepository.getRoutes();
}
public LiveData<List<RoutesResponse>> getRoutes() {
return routes;
}
}
目前出现空指针错误。如何正确避免这个错误?
java.lang.NullPointerException: 尝试在空对象引用上调用虚拟方法 'void androidx.lifecycle.LiveData.observe(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Observer)'
英文:
I'm using the MVVM architecture. I have an activity and a few fragments, I would like to make a request in the API in the activity, and then using ViewModel, thanks to the obtained data, to display them in the fragment. How should I do this? My current solution that doesn't work:
Activity:
viewModelRoutesFragment = new ViewModelProvider(this).get(ViewModelRoutesFragment.class);
viewModelRoutesFragment.init();
Fragment:
viewModelRoutesFragment = new ViewModelProvider(this).get(ViewModelRoutesFragment.class);
viewModelRoutesFragment.getRoutes().observe(getActivity(), new Observer<List<RoutesResponse>>() {
@Override
public void onChanged(List<RoutesResponse> routes) {
//Show data
}
});
Repository:
public class RemoteRepository {
private ApiRequest apiRequest;
private MutableLiveData<List<RoutesResponse>> routes = new MutableLiveData<>();
public RemoteRepository() {
apiRequest = RetrofitRequest.getInstance().create(ApiRequest.class);
}
public MutableLiveData<List<RoutesResponse>> getRoutes() {
apiRequest.getRoutes()
.enqueue(new Callback<List<RoutesResponse>>() {
@Override
public void onResponse(Call<List<RoutesResponse>> call, Response<List<RoutesResponse>> response) {
if (response.isSuccessful())
routes.setValue(response.body());
}
@Override
public void onFailure(Call<List<RoutesResponse>> call, Throwable t) {
Log.i("Failure", "Fail!");
}
});
return routes;
}
}
ViewModel:
public class ViewModelRoutesFragment extends AndroidViewModel {
private RemoteRepository remoteRepository;
private LiveData<List<RoutesResponse>> routes;
public ViewModelRoutesFragment(@NonNull Application application) {
super(application);
}
public void init() {
remoteRepository = new RemoteRepository();
routes = remoteRepository.getRoutes();
}
public LiveData<List<RoutesResponse>> getRoutes() {
return routes;
}
}
Currently getting a null error. How can I avoid it properly?
java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.lifecycle.LiveData.observe(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Observer)' on a null object reference
答案1
得分: 10
在Fragment中
使用
viewModelRoutesFragment = new ViewModelProvider(requireActivity()).get(ViewModelRoutesFragment.class);
而不是
viewModelRoutesFragment = new ViewModelProvider(this).get(ViewModelRoutesFragment.class);
英文:
in Fragment
Use
viewModelRoutesFragment = new ViewModelProvider(requireActivity()).get(ViewModelRoutesFragment.class);
instead of
viewModelRoutesFragment = new ViewModelProvider(this).get(ViewModelRoutesFragment.class);
答案2
得分: 6
基本上,我们正在尝试在活动(activity)和片段(fragment)之间共享 ViewModel。因此,在活动创建期间,我们必须创建 ViewModel 的实例:
viewModelRoutesFragment = new ViewModelProvider(requireActivity()).get(ViewModelRoutesFragment.class);
viewModelRoutesFragment.init();
在片段中,我们还需要重用 ViewModelRoutesFragment,在 onViewCreated()
方法中获取 ViewModel 实例并观察 LiveData:
viewModelRoutesFragment = new ViewModelProvider(requireActivity()).get(ViewModelRoutesFragment.class);
viewModelRoutesFragment.getRoutes().observe(getActivity(), new Observer<List<RoutesResponse>>() {
@Override
public void onChanged(List<RoutesResponse> routes) {
// 更新 UI
}
});
英文:
Basically, we are trying to share the viewmodel across the activity and fragment.
so while during the activity creation we have to create the instance of viewmodel
viewModelRoutesFragment = new ViewModelProvider(requireActivity()).get(ViewModelRoutesFragment.class);
viewModelRoutesFragment.init();
In fragment also we need to reuse the ViewModelRoutesFragment so in onViewCreated()
get the instance of the ViewModel and observe the live data
viewModelRoutesFragment = new ViewModelProvider(requireActivity()).get(ViewModelRoutesFragment.class);
viewModelRoutesFragment.getRoutes().observe(getActivity(), new Observer<List<RoutesResponse>>() {
@Override
public void onChanged(List<RoutesResponse> routes) {
// updation of UI
}
});
答案3
得分: 1
你不需要在活动中使用视图模型引用。您应该在活动内部拥有片段的实例。您的片段已经持有对ViewModel的引用。从活动中删除这些行 -> :
viewModelRoutesFragment = new ViewModelProvider(this).get(ViewModelRoutesFragment.class);
viewModelRoutesFragment.init();
确保在活动中初始化您的片段。您的活动只是一个容器块,实际上会使用片段管理器替换片段。如果您正在与片段一起使用,它不需要任何ViewModel。
此外,在以下行的下方,在片段内调用此方法 viewModelRoutesFragment.init();
viewModelRoutesFragment = new ViewModelProvider(this).get(ViewModelRoutesFragment.class);
英文:
You don't need your view model reference in the activity. You should have an instance of fragments inside the activity. Your fragment already holding a reference to the ViewModel. Delete these line from the activity -> :
viewModelRoutesFragment = new ViewModelProvider(this).get(ViewModelRoutesFragment.class);
viewModelRoutesFragment.init();
Make sure you initialize your fragment in activity. Your activity is just a holder block, which actually replace the fragment using fragment manager. It doenst required any viewmodel if you are using a fragment with it.
Also, call this method inside your fragment viewModelRoutesFragment.init();
below this line
viewModelRoutesFragment = new ViewModelProvider(this).get(ViewModelRoutesFragment.class);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论