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();
}
ViewModel
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;
}
答案 0 :(得分:3)
Activity不应包含任何MutablieLiveData成员变量,而该变量必须位于ViewModel中。
之所以只能在第一次使用,是因为您第一次观察到某些内容已被更改,但是由于您的排列不正确,它永远不会再更新。也就是说,由于使用新的一组MutableLiveData在ViewModel内再次重新创建了ArticleRepository,因此您所订阅的上一个已不再相关-您只onCreate()
订阅一次。
您应将绑定与异步任务(例如loadData()
)分开,它们不是同一回事。绑定是您在开始收集MutableLiveData(在loadData中正在执行的操作)时要做的事情,但是一旦完成该操作,就不要再这样做了。
我还指出,您实际上是在模型中包含LiveData,因此不建议这样做,因为它会破坏模式并带来其他问题。应该由ViewModel来准备演示文稿,而不是准备存储库。由于当前已配置事物,因此您的存储库也可以称为ViewModel。相反,您应该做的是使用可观察对象将新批次通知ViewModel,以发布或处理可能发生的错误。
研究此示例:https://developer.android.com/topic/libraries/architecture/viewmodel
请注意,loadUsers()
在调用getUsers()
时执行一次。这就是将Activity绑定到ViewModel的原因。但是loadUsers()
可以稍后再做,应该将更改发布到ViewModel中的LiveData中。
答案 1 :(得分:1)
不应每次加载更多照片时new MutableLiveData()
,而应在单个postValue
对象上调用MutableLiveData
。下面的示例代码:
ViewModel:
public class ArticleViewModel extends ViewModel {
private MutableLiveData<List<Photo>> photos;
public MutableLiveData<List<Photo>> getPhotoList() {
Log.d(TAG, "loadData");
if (photos == null) {
photos = new MutableLiveData<>();
loadPhotos();
}
return photos;
}
public void loadPhotos() {
Log.d(TAG, "getArticleList");
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");
List<Photo> morePhotos = response.body();
List<Photo> allPhotos = new ArrayList<>();
allPhotos.addAll(photos.getValue());
allPhotos.addAll(morePhotos);
photos.postValue(allPhotos); // <--- post change here
}
}
@Override
public void onFailure(Call<List<Photo>> call, Throwable t) {
Log.d(TAG, "onFailure: " + t.getMessage() + "\n" + t.getStackTrace());
}
});
}
}
MainActivity:
public class MainActivity extends AppCompatActivity
private ArticleViewModel mArticalViewModel;
// some code...
@Override
protected void onCreate(Bundle savedInstanceState) {
mArticalViewModel = ViewModelProviders.of(this).get(ArticleViewModel.class);
mArticleViewModel.getPhotoList().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?");
mArticleViewModel.loadPhotos(); // <--- changed here
}
}
});
}
答案 2 :(得分:0)
是回收器适配器“arraylist.addAll 或 list.addAll”中的“mAdapter.updateList”函数,viewModel 中的“loadPhotos”函数是否称为 onCreate?如果是这样,请尝试将“arraylist.addAll 或 list.addAll”更改为“arraylist = data 或 list = data”。并将 loadmore 函数与 firstCallApi(您放在 onCreate 中的视图模型函数)分开。
所以 loadmore 函数用于更新数据,而 firstCall 用于初始数据。观察加载更多插入代码“arraylist.addAll 或 list.addAll”和 firstCall 插入“list = data”。
示例: https://gist.github.com/kazuiains/c52f9fc597b66c05b7ec0439a0bb4ccb