【问题标题】:How to insert/remove items from RecyclerView using MVP [closed]如何使用 MVP 从 RecyclerView 插入/删除项目 [关闭]
【发布时间】:2016-09-30 14:08:23
【问题描述】:

在 MVP 中使用回收器视图时,你们在哪里保留对列表的引用?我有一个ChatManager,可以与不同的演示者交谈。我保留了两份消息列表,一份在ChatManager,另一份在Presenter。适配器、视图和演示者共享同一个列表。 我之所以引用 Presenter 中的消息列表,是因为我有一些要从演示者那里处理的删除和滚动业务逻辑。

所以现在当我必须删除一条消息时,演示者决定要删除的项目并将其从列表中删除。现在它需要让视图知道一条消息已被删除。那么在这种情况下,应该说view.remove(message) 还是view.remove(index)?视图不应再次尝试删除消息,因为演示者已经这样做了。

滚动或添加等其他操作也是如此。如果收到新消息,演示者会将newMessages 添加到allMessages,然后必须更新视图。理想情况下,演示者应该调用view.onMessagesReceived(List<Message> messages) 而不是view.onMessageReceived(int newMessagesCount, int indexAddedAt)。第二种方法真的很奇怪,一点也不冗长。但是由于列表是共享的,视图只需要调用notifyItemInserted,因此只需要知道计数和索引。

处理这个问题的最佳方法是什么?

【问题讨论】:

  • 我是这样做的:我将数据列表存储在演示者中,无需复制即可查看。当演示者(来自模型)发生变化时,我可以调用view.changeData(),您的活动/片段可以通过presenter.getData() 访问数据。与视图相关的操作具有与演示者相关的方法(添加新消息,加载更多......)
  • @akshayt23 第一次设置数据列表 view.onMessagesReceived(List messages) 在任何更改(添加、编辑、删除)影响后的选项流如 notifyItemInserted(int lastPostion) Edit NotifyItemChanged(int position ) 通过唯一 ID 从消息中获取位置删除也相同

标签: android architecture android-recyclerview mvp


【解决方案1】:

因此,正如 Amir 建议的那样,一种方法是从适配器公开一个方法来更新数据,然后调用 notifyDataSetChanged。我真的不想使用这种方法,因为当我只想在适配器中添加/更新消息时,它会不必要地刷新整个数据集。

另一种方法是在视图中公开一个方法addNewMessages(int count, int index),以便适配器知道要通知插入/更新的索引,我再次不想使用它,因为API 看起来很奇怪addNewMessages实际上应该传递新消息列表而不是索引和计数。

我采用的解决方案实际上是将整个更新列表从Presenter 传递给View,最终将它传递给Adapter。然后Adapter 使用DiffUtil 找出旧列表和新列表之间的差异,并且每次只调用notifyItemInserted/notifyItemChanged 方法而不是notifyDataSetChanged

这很有帮助,因为现在 API 看起来像这样:

ChatPresenter {
    interface View {
    ...
    void updateMessages(List<Message> messages);
}

Activity implements ChatPresenter.View {
    ...
    @Override
    void updateMessages(List<Message> messages) {
        chatsAdapter.update(messages);
    }
}

ChatsAdapter {
    ...
    public update(List<Message> messages) {
        DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new ChatMessageDiffCallback(this.messages, updatedMessages));

        this.messages = updatedMessages;
        diffResult.dispatchUpdatesTo(this);
    }
}

【讨论】:

    【解决方案2】:

    最佳实践是从视图实现中更新适配器列表,但此任务的功能应该在视图接口上并在视图实现中实现(例如片段或活动)

    首先向您的适配器添加一个方法,如下所示

    public void updateItemsList(ItemsList itemsList)
    {
       //update the list of your items assume your items list is named "mItemsList"
       this.mItemsList = itemsList;
       notifyDataSetChanged();
    }
    

    然后在您的视图界面中添加一个方法来更新适配器列表,如下所示

    public void updateAdapterList(ItemsList itemsList);
    

    然后在您的视图实现(片段或活动)中添加:

    @Override
    public void updateAdapterList(ItemsList itemsList);
    {
       //update the adapter list -- assume your adapter is named "mAdapter"
       mAdapter.updateItemsList(itemsList);
    }
    

    现在您可以在任何有视图接口类型的对象的地方访问此方法 (updateAdapterList())。

    【讨论】:

      猜你喜欢
      • 2016-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-25
      • 2015-11-16
      • 1970-01-01
      • 1970-01-01
      • 2020-07-27
      相关资源
      最近更新 更多