如果列表中的某个item数据发生微小变化而需要更新UI状态,直接notifyDataSetChanged()的方式会影响性能,今天看到Android官方的列表局部更新方式,分享给大家:
void onNewDataArrived(List<News> news) {
List<News> oldNews = myAdapter.getItems();
DiffResult result = DiffUtil.calculateDiff(new MyCallback(oldNews, news));
myAdapter.setNews(news);
result.dispatchUpdatesTo(myAdapter);
}
//只需将您的 MyCallback 定义为 DiffUtil.Callback 实现,以通知 DiffUtil 如何检查您的列表即可。
另外还有RecyclerView的嵌套问题,也有详细的解释
RecyclerView:嵌套的 RecyclerView
嵌套 RecyclerView
很常见,对于由水平滚动列表组成的纵向列表(例如 Play 商店主页面上的应用网格),尤其如此。这种方法效果很好,但它也会导致大量来回移动的视图。在首次向下滚动页面时,如果您看到大量内部内容出现扩充,则可能需要检查内部(水平)RecyclerView 之间是否正在共享 RecyclerView.RecycledViewPool
。默认情况下,每个 RecyclerView 都将有自己的内容池。然而,在屏幕上同时显示十几个 itemViews
的情况下,如果所有行都显示类型相似的视图,那么当不同的水平列表无法共享 itemViews
时,就会出现问题。
class OuterAdapter extends RecyclerView.Adapter<OuterAdapter.ViewHolder> { RecyclerView.RecycledViewPool sharedPool = new RecyclerView.RecycledViewPool(); ... @Override public void onCreateViewHolder(ViewGroup parent, int viewType) { // inflate inner item, find innerRecyclerView by ID… LinearLayoutManager innerLLM = new LinearLayoutManager(parent.getContext(), LinearLayoutManager.HORIZONTAL); innerRv.setLayoutManager(innerLLM); innerRv.setRecycledViewPool(sharedPool); return new OuterAdapter.ViewHolder(innerRv); } ...
如果您希望进一步优化,还可以对内部 RecyclerView 的 LinearLayoutManager
调用 setInitialPrefetchItemCount(int)
。例如,如果您始终在某行中显示 3.5 项内容,请调用 innerLLM.setInitialItemPrefetchCount(4);
。这将向 RecyclerView 表明,当某个水平行即将显示在屏幕上时,如果界面线程中有空余时间,RecyclerView 应尝试预取该行中的内容。