【问题标题】:How to use ViewModel in a fragment?如何在片段中使用 ViewModel?
【发布时间】:2020-08-23 14:48:55
【问题描述】:

我正在使用 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) {

                //Show data
    }
});

存储库:

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;
    }
}

视图模型:

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: Attempt to invoke virtual method 'void androidx.lifecycle.LiveData.observe(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Observer)' on a null object reference

【问题讨论】:

标签: java android android-fragments mvvm android-livedata


【解决方案1】:

基本上,我们试图在活动和片段之间共享视图模型。 所以在活动创建期间,我们必须创建视图模型的实例

viewModelRoutesFragment = new ViewModelProvider(requireActivity()).get(ViewModelRoutesFragment.class);
viewModelRoutesFragment.init();

在片段中我们还需要重用 ViewModelRoutesFragment 所以在 onViewCreated() 获取 ViewModel 的实例并观察实时数据

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
    }
});

【讨论】:

    【解决方案2】:

    在片段中 使用

    viewModelRoutesFragment = new ViewModelProvider(requireActivity()).get(ViewModelRoutesFragment.class);
    

    而不是

    viewModelRoutesFragment = new ViewModelProvider(this).get(ViewModelRoutesFragment.class);
    

    【讨论】:

      【解决方案3】:

      您不需要在活动中引用您的视图模型。您应该在 Activity 中有一个片段实例。您的片段已经持有对 ViewModel 的引用。从活动中删除这些行 -> :

      viewModelRoutesFragment = new ViewModelProvider(this).get(ViewModelRoutesFragment.class);
      viewModelRoutesFragment.init();
      

      确保在活动中初始化您的片段。您的活动只是一个持有者块,它实际上使用片段管理器替换片段。如果您使用片段,它不需要任何视图模型。

      另外,在你的片段中调用这个方法viewModelRoutesFragment.init(); 在这条线以下

       viewModelRoutesFragment = new ViewModelProvider(this).get(ViewModelRoutesFragment.class);
      

      【讨论】:

        猜你喜欢
        • 2021-04-23
        • 1970-01-01
        • 2023-02-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多