在 MVP 中使用回收 View 时,你们在哪里保留对列表的引用?我有一个 ChatManager
可以与不同的主持人交谈。我保留了两份消息列表,一份在 ChatManager
中。另一个在Presenter
.适配器、 View 和演示者共享同一个列表。
我引用 Presenter
中的消息列表的原因是因为我有一些要从演示者那里处理的删除和滚动业务逻辑。
所以现在当我必须删除一条消息时,演示者会决定要删除的项目并将其从列表中删除。现在它需要让 View 知道消息已被删除。那么在那种情况下,它应该说view.remove(message)
吗?或 view.remove(index)
? View 不应再次尝试删除消息,因为演示者已经这样做了。
滚动或添加等其他操作也是如此。如果收到新消息,演示者将添加 newMessages
至 allMessages
然后必须更新 View 。理想情况下,演示者应该调用 view.onMessagesReceived(List<Message> messages)
而不是 view.onMessageReceived(int newMessagesCount, int indexAddedAt)
.第二种方法真的很奇怪,一点也不冗长。但由于列表正在共享, View 只需要调用 notifyItemInserted
因此只需要知道计数和索引。
处理这个问题的最佳方法是什么?
正如 Amir 所建议的那样,一种解决方法是从适配器公开一个方法来更新数据,然后调用 notifyDataSetChanged
。我真的不想使用这种方法,因为当我只想在适配器中添加/更新消息时,它会不必要地刷新整个数据集。
另一种方法是在 View 中公开一个方法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);
}
}