java - 为什么 LiveData setValue 或 PostValue 在视图中只触发一次 onChange?
问题描述
LiveData setValue 应该触发了 Activity 中的 onChanged 方法,但是它只在第一次调用,当我尝试进行分页之后,它会中断并且不再调用 onChanged,尽管我的响应确实成功并且我看到它在日志。setValue/postValue 有什么问题?它是一个错误吗?我应该自己实现观察者模式吗?那么使用 LiveData 有什么意义呢?我的寻呼仅在这 2-3 天后不起作用.....
MainActivity 类
public class MainActivity extends AppCompatActivity private MutableLiveData<List<Photo>> mLivePhotos; // some code... @Override protected void onCreate(Bundle savedInstanceState) { mLivePhotos = loadData(); mLivePhotos.observe(this, photos -> { Log.d(TAG, "onChanged!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); mProgressBar.setVisibility(View.GONE); mPhotos = photos; if (mIsInitialCall) { initiateAdapter(); mIsInitialCall = false; } else { mAdapter.updateList(mPhotos.subList(mPageNumber, mPageNumber + 10)); } }); mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { int lastPosition = mLayoutManager.findLastCompletelyVisibleItemPosition(); Log.d(TAG, "onScrolled - lastPosition: " + lastPosition); if (lastPosition == mLayoutManager.getItemCount() - 1) { Log.d(TAG, "onScrolled - End of list?"); loadData(); } } }); } private MutableLiveData<List<Photo>> loadData() { Log.d(TAG, "loadData"); if (mArticleViewModel == null) return null; mPageNumber += 10; mProgressBar.setVisibility(View.VISIBLE); return mArticleViewModel.loadPhotos(); }
视图模型
public class ArticleViewModel extends ViewModel { private MutableLiveData<List<Photo>> photos; private ArticleRepository articleRepository; public MutableLiveData<List<Photo>> loadPhotos() { Log.d(TAG, "getArticleList"); //TODO; add Dagger 2 articleRepository = new ArticleRepository(); photos = articleRepository.getPhotos(); return photos; }
存储库
public class ArticleRepository { public MutableLiveData<List<Photo>> getPhotos() { final MutableLiveData<List<Photo>> result = new MutableLiveData<>(); Log.d(TAG, "getResults"); ApiService.getService().getPhotos().enqueue(new Callback<List<Photo>>() { @Override public void onResponse(Call<List<Photo>> call, Response<List<Photo>> response) { Log.d(TAG, "onResponse"); if (response.isSuccessful()) { Log.d(TAG, "isSuccessful"); result.postValue(response.body()); } } @Override public void onFailure(Call<List<Photo>> call, Throwable t) { Log.d(TAG, "onFailure: " + t.getMessage() + "\n" + t.getStackTrace()); } }); return result; }
解决方案
Activity 不应该有任何 MutablieLiveData 成员变量,它应该在 ViewModel 中。
它只在第一次工作的原因是因为你第一次观察到它通知的东西已经改变,但是因为你的安排不正确,它永远不会再更新。也就是说,因为 ArticleRepository 在您的 ViewModel 中再次使用一组新的 MutableLiveData 重新创建,所以您订阅的前一个不再相关 - 您只订阅一次onCreate()
。
您应该将绑定与异步任务分开,因为loadData()
它们不是同一件事。绑定是您在开始收集 MutableLiveData(您在 loadData 中所做的事情)时所做的事情,但在您完成之后,您不应该再做一次。
我还注意到您实际上在模型中有 LiveData,不建议这样做,因为它会破坏模式并可能带来其他问题。准备演示文稿的是 ViewModel,而不是 Repository。由于您当前已经配置了一些东西,您的存储库也可以称为 ViewModel。相反,您应该做的是使用 observables 通知 ViewModel 有一个新批次来发布或处理可能发生的错误。
研究这个例子:https ://developer.android.com/topic/libraries/architecture/viewmodel
请注意,调用loadUsers()
时getUsers()
会执行一次。这就是将 Activity 绑定到 ViewModel 的原因。但loadUsers()
可以稍后再完成,并且应该将更改发布到 ViewModel 内的 LiveData。
推荐阅读
- javascript - 当轴在中间对齐时如何制作网格线?
- google-cloud-platform - 如何使用流式 insertAll 在 BigQuery 中插入 38000 条记录?
- android - android.speech.RecognizerIntent 的包名是什么?
- sql - 我对 SQL COUNT 的使用没有按预期工作
- java - 如何创建带有字符串的二维数组?
- python - 访问列表 Python 中的字典
- docker - Nginx 日志不显示
- javascript - Dynamically Split a table cell into multiple columns depending on the comma
- python - 如何同时运行阻塞函数?
- php - 从 Curl 输出字符串数据类型数据中过滤掉 json 字符串