私は2つのフラグメントの簡単なセットアップを持っています:ConversationFragment
そしてDetailsFragment
とを使用Room
して、に属する と一緒に実装を使用しています。Paging 3 library
ConversationFragment
PagingLiveData
AndroidViewModel
ConversationFragment
ここでは使用していませんNavigation Components
。Android のドキュメントにある一般的なフラグメント ナビゲーションです。
そのフラグメントから を開き、DetailsFragment
再びフラグメントに戻ることができます。上記のフラグメントを開いて戻るまで、すべてがうまく機能していConversationFragment
ますDetailsFragment
.
これまでのところ、これは大きな問題ではありません。オブザーバーを再起動することができ、それを行うと機能します。ただし、オブザーバーを再度アタッチすると、リスト全体がリフローし、これによりアイテムが暴走し、RecyclerView
リストの位置が失われ、スクロールバーのサイズが変更され、ページがロード/リロードされていることが確認されます。
異様な振る舞いはある程度は耐えられたが、その上でポジションを失うのは許されない。
LiveData<PagingData<...>
ビューモデルで結果をキャッシュすることを検討しましたが、利用可能なドキュメントで見つけることができる例は基本的なものであり、オブジェクトを使用して同じことを達成する方法を示していません.
現在、これは私が持っているものです:
ConversationFragment
@Override
public void onViewCreated(
@NonNull View view,
@Nullable Bundle savedInstanceState
) {
if (viewModel == null) {
viewModel = new ViewModelProvider(this).get(ConversationViewModel.class);
}
if (savedInstanceState == null) {
// adapter is initialized in onCreateView
viewModel
.getList(getViewLifecycleOwner())
.observe(getViewLifecycleOwner(), pagingData -> adapter.submitData(lifecycleOwner.getLifecycle(), pagingData));
}
super.onViewCreated(view, savedInstanceState);
}
ConversationViewModel
public class ConversationViewModel extends AndroidViewModel {
final PagingConfig pagingConfig = new PagingConfig(10, 10, false, 20);
private final Repository repository;
private final MutableLiveData<PagingData<ItemView>> messageList;
public ConversationFragmentVM(@NonNull Application application) {
super(application);
messageList = new MutableLiveData<>();
repository = new Repository(application);
}
public LiveData<PagingData<ItemView>> getList(@NonNull LifecycleOwner lifecycleOwner) {
// at first I tried only setting the value if it was null
// but since the observer is lost on destroy and the value
// is not it would never be able to "restart" the observer
// again
// if (messageList.getValue() == null) {
PagingLiveData.cachedIn(
PagingLiveData.getLiveData(new Pager<>(pagingConfig, () -> repository.getMessageList())),
lifecycleOwner.getLifecycle()
).observe(lifecycleOwner, messageList::setValue);
// }
return messageList;
}
}
そのまま結果をPagingLiveData.cachedIn
返しても、フラグメントに戻ったときの動作は同じです。recyclerview リストで項目が不規則な動作を示し、それがあった位置が完全に失われます。
これは、私の問題が解決したかどうかを確認するために達成しようとしていたものです。
これは、 https ://developer.android.com/codelabs/android-training-livedata-viewmodel#8 で利用できるコードラボです。
ご覧のmAllWords
とおり、キャッシュされ、ビューモデルが初めて構築されたときにのみ初期化されます。その後の変更は単純に更新され、新しいオブザーバーを接続する必要があるのは、フラグメントが破棄され、まだフラグメント内にある間に再度作成された場合のみです。バックスタック。
これは私がやろうとしていたことですが、思ったようには機能しません。少なくとも、思ったほど簡単ではありません。
これはどのように達成できますか?