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);
...
}
@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() {...}
...
}
}
DiffUtil を使用すると、巨大なリストの1つの行を更新するのに役立ちます。その後、1つのコメントまたはコメントの属性の代わりに、LiveDataにコメントのリストをラップさせることができます。
RecyclerViewアダプター および フラグメント内のLiveData観測コードのリスト 内でDiffUtilを使用する例を次に示します。
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);
}
}