LiveData setValueは、アクティビティで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;
}
アクティビティには、ViewModel内にあるMutablieLiveDataメンバー変数があってはなりません。
初めてしか機能しない理由は、最初に何かを観察したときに変更されたと通知するためですが、配置が正しくないため、二度と更新されません。つまり、ArticleRepositoryは新しいMutableLiveDataのセットを使用してViewModel内で再作成されるため、以前にサブスクライブしたものは関連しなくなり、onCreate()
を1回だけサブスクライブします。
バインドをloadData()
などの非同期タスクから分離する必要があります。これらは同じものではありません。バインディングは、MutableLiveData(loadDataで実行していること)を収集するために最初に行うことですが、一度実行した後は、再度実行しないでください。
また、実際にはモデル内にLiveDataがあることにも注意しました。パターンが壊れたり、他の問題が発生したりする可能性があるため、この方法で行うことはお勧めしません。プレゼンテーションを準備するのはViewModelであり、リポジトリではありません。現在設定しているので、リポジトリはViewModelと呼ばれることもあります。代わりに、オブザーバブルを使用して、発生した可能性のあるエラーを投稿または処理するための新しいバッチをViewModelに通知する必要があります。
この例を調べてください: https://developer.Android.com/topic/libraries/architecture/viewmodel
loadUsers()
は、getUsers()
が呼び出されたときに1回実行されることに注意してください。これは、アクティビティをViewModelにバインドするものです。ただし、loadUsers()
は後で再度実行でき、ViewModel内のLiveDataへの変更を投稿する必要があります。
写真を追加するたびに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());
}
});
}
}
主な活動:
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
}
}
});
}