1

私は2つのフラグメントの簡単なセットアップを持っています:ConversationFragmentそしてDetailsFragment

とを使用Roomして、に属する と一緒に実装を使用しています。Paging 3 libraryConversationFragmentPagingLiveDataAndroidViewModelConversationFragment

ここでは使用していません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とおり、キャッシュされ、ビューモデルが初めて構築されたときにのみ初期化されます。その後の変更は単純に更新され、新しいオブザーバーを接続する必要があるのは、フラグメントが破棄され、まだフラグメント内にある間に再度作成された場合のみです。バックスタック。

これは私がやろうとしていたことですが、思ったようには機能しません。少なくとも、思ったほど簡単ではありません。

これはどのように達成できますか?

4

1 に答える 1