web-dev-qa-db-ja.com

Android LiveDataでRecyclerViewを更新します

LiveDataの変更時に新しいリストをアダプターにプッシュする方法は多数あります。

巨大なリストの1行(たとえば、投稿のコメント数)を更新しようとしています。リスト全体をリセットして1つのフィールドのみを変更するのは愚かなことです。

オブザーバーonBindViewHolderを追加できますが、オブザーバーをいつ削除する必要があるのか​​理解できません

@Override
public void onBindViewHolder(ViewHolder vh, int position) {
    Post post = getPost(position);
    vh.itemView.setTag(post);
    post.getLiveName().observeForever(vh.nameObserver);
    ... 
}
26
Andrew Matuk

@Lylaが言ったように、リスト全体をフラグメントまたはアクティビティでLiveDataとして観察する必要があります。変更を受信した場合、DiffUtilでリスト全体をアダプターに設定する必要があります。

偽のコード:

PostViewModel {
    LiveData<List<Post>> posts;  // posts comes from DAO or Webservice
}

MyFragment extends LifecycleFragment {
    PostAdapter postAdapter;

    ...

    void onActivityCreated() {
        ...
        postViewModel.posts.observer(this, (postList) -> {
            postAdapter.setPosts(postList);
        }
    }       
}

PostAdapter {
    void setPosts(List<Post> postList) {
        DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() {...}
        ...
    }
}
13
Spark.Bao

DiffUtil を使用すると、巨大なリストの1つの行を更新するのに役立ちます。その後、1つのコメントまたはコメントの属性の代わりに、LiveDataにコメントのリストをラップさせることができます。

RecyclerViewアダプター および フラグメント内のLiveData観測コードのリスト 内でDiffUtilを使用する例を次に示します。

10
Lyla

Transformations.switchMap()を使用して、基になるPostオブジェクトを交換します。その後、セルがリサイクルされたときにオブザーバーを削除して追加し直す必要はありません。

@Override
public void onBindViewHolder(PostViewHolder vh, int position) {
    Post post = getPost(position);
    vh.bind(post);
}

次に、ViewHolderクラスで

public class PostViewHolder extends RecyclerView.ViewHolder {
    private final MutableLiveData<Post> post = new MutableLiveData<>();

    public PostViewHolder(View itemView) {
        super(itemView);

        LiveData<String> name = Transformations.switchMap(post, new Function<Post, LiveData<String>>() {
            @Override
            public LiveData<String> apply(Post input) {
                return input.getLiveName();
            }
        });

        name.observeForever(new Observer<String>() {
            @Override
            public void onChanged(@Nullable String name) {
                // use name
            }
        });
    }

    public void bind(Post post) {
        post.setValue(post);
    }
}
3
tom-pratt