35

有很多示例如何在 LiveData 更改时将新列表推送到适配器。

我正在尝试更新庞大列表中的一行(例如帖子的评论数)。重置整个列表以仅更改一个字段是愚蠢的。

我可以在BindViewHolder 上添加观察者,但我不明白什么时候应该删除观察者

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

5 回答 5

20

就像@Lyla 说的那样,您应该在 Fragment 或 Activity 中将整个列表观察为 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() {...}
        ...
    }
}
于 2017-06-30T02:33:05.463 回答
13

使用DiffUtil可能有助于更新巨大列表中的一行。然后,您可以让 LiveData 包装评论列表,而不是单个评论或评论的属性。

这是在RecyclerView 适配器中使用 DiffUtil 的示例,并在片段中列出 LiveData 观察代码

于 2017-06-30T02:06:15.557 回答
4

用于Transformations.switchMap()交换基础Post对象。那么在cell被回收的时候就不需要移除和重新添加observers了。

@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);
    }
}
于 2018-02-07T13:12:33.310 回答
0

我认为您应该将LiveAdapter用于 RecyclerView 适配器,而不是为适配器创建一个额外的类。

它也有 DiffUtil 实现,因此只会更新单个项目。并且不调用 notifyDatasetChange。

// Kotlin sample
LiveAdapter(
            data = liveListOfItems,
            lifecycleOwner = this@MainActivity,
            variable = BR.item )
           .map<Header, ItemHeaderBinding>(R.layout.item_header) {
               onBind{

               }
               onClick{

               }
               areContentsTheSame { old: Header, new: Header ->
                   return@areContentsTheSame old.text == new.text
               }
               areItemSame { old: Header, new: Header ->
                   return@areContentsTheSame old.text == new.text
               }
           }
           .map<Point, ItemPointBinding>(R.layout.item_point) {
               onBind{

               }
               onClick{

               }
               areContentsTheSame { old: Point, new: Point ->
                   return@areContentsTheSame old.id == new.id
               }
               areItemSame { old: Header, new: Header ->
                   return@areContentsTheSame old.text == new.text
               }
           }
           .into(recyclerview)
于 2021-06-03T23:24:02.793 回答
-1

添加context到您的adapterClass委托人:AdpaterClass(context: Context)

context然后智能投到AppCompactActivity

livedata.observe(context as AppCompatActivity, Observer {it ->

        //perform action on it(livedata.value)
    })

adapter从任何地方调用时activityfragmentcontextadpater

于 2020-06-29T23:13:07.173 回答