ViewModel 中的 LiveData 未更新

LiveData not updated in ViewModel

在我的 ViewModel class 中,我有一个方法可以从互联网上获取数据并通过 setValue() 将它们设置在 LiveData 上(我使用了这些 docs 中的方法):

public class PageViewModel extends ViewModel {  
private MutableLiveData<List<?>> mDataList;
...


private LiveData<List<?> getDataList() {
    if (mDataList == null) {
        mDataList = new MutableLiveData<>();
    }

    Handler handler = new Handler(Looper.getMainLooper());
    // getData() connects to the internet and fetches the online data 
    mInternetConnection.getData(new InternetConnection.ConnectionCallback<List<?>>() {
        @Override
        public void onComplete(Result<List<?>> result) {
            if (result instanceof Result.Success) {
                mDataList.setValue(((Result.Success<List<?>>) result).data);
            } else {
                Log.e(LOG_TAG, "ViewModel could not obtain data list");
            }
        }
    }, handler);
    
    return mDataList;
}

但是 mDataList.getValue() 为空。 setValue() 方法在主线程上被调用。 onComplete 肯定会被调用(选中)。

当我在 setValue() 之后的 onComplete 方法中检查 mDataList 的值是否为空时,日志显示它不为空。

为什么是null,修改后的mDataList的值应该如何获取?

我花了几个小时在网上寻找解决方案,但找不到任何有用的东西。本站相关问题也无助于解决问题

编辑:

来自 docs在这个例子中,传递给 Repository 的 makeLoginRequest 调用的回调在主线程上执行。这意味着您可以直接从回调中修改 UI 或使用 LiveData.setValue() 与 UI.

通信

所以我遵循了那个,但是这部分:“或使用 LiveData.setValue() 与 UI 通信”不起作用。

Fragment 中设置了观察者,但 LiveData 仍然没有更新 - list in onChanged 为 null,屏幕保持空白,没有错误。

片段代码:

@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    binding = FragmentMainBinding.inflate(inflater, container, false);
    View rootView = binding.getRoot();
    binding.listRecyclv.setLayoutManager(new LinearLayoutManager(rootView.getContext()));
    mAdapter = createAdapter(rootView.getContext(), pageViewModel.getList().getValue());
    binding.listRecyclv.setAdapter(mAdapter);

    pageViewModel.getList().observe(getViewLifecycleOwner(), new Observer<List<?>>() {
    @Override
    public void onChanged(@Nullable List<?> list) {         
            mAdapter.setList((ArrayList<MyObj>) list);
            binding.listRecyclv.setAdapter(mAdapter);
            }
    }
}

});

Getter 在视图模型中:

public LiveData<List<?>> getList() {
    return getDataList();
}

适配器中的代码:

public class AppAdapter extends RecyclerView.Adapter<AppAdapter.AppViewHolder> {

...

public void setList(ArrayList<MyObj> list) {
    mAppList = list;
    notifyDataSetChanged();
}

提前致谢。

mDataList 为空,因为您为获取数据所做的调用是 asynchronous。这意味着该函数将在您的 api 调用(及其回调)之前 return。

在此处阅读更多内容 https://www.bmc.com/blogs/asynchronous-programming/

要获取列表,您需要观察数据变化。

所以像这样:

来自activity:

科特林:

viewModel.getDataList().observe(this) { dataList ->
  //TODO: Do something with the list
}

Java:

final Observer<String> listObserver = new Observer<List<>>() {
   @Override
   public void onChanged(@Nullable final List<> newName) {
      //TODO: Use the list
   }
};

viewModel.getDataList().observe(this, listObserver);

每次列表更改时都会调用观察者内部的逻辑。

我是这样解决的:

  1. 在 Fragment 的 onCreate 方法中更改了这一行

来自:

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

pageViewModel = new  ViewModelProvider(this).get(PageViewModel.class);

pageViewModel = new ViewModelProvider(requireActivity()).get(PageViewModel.class);

感谢

  1. 将 PageViewModel class 中 getDataList() 方法的数据类型从 LiveData 更改为 MutableLiveData(如果没有它,上述步骤将无济于事):

来自:

public class PageViewModel extends ViewModel {  
    private MutableLiveData<List<?>> mDataList;
    ...


    private LiveData<List<?> getDataList() {

至:

    private MutableLiveData<List<?> getDataList() {

现在可以了!现在触发观察器并更新数据。