Android开发:如何让RecyclerView即时显示已加载完成的条目?
嘿,针对你的两个问题,我来分享下实际Android开发里的常用解法:
其实很简单——不要等所有数据都准备好再更新Adapter。当第一条数据刚加载完成(不管是从网络拿到还是本地解析好),直接把它加入到Adapter的数据集里,然后调用notifyItemInserted(0)(因为是第一个条目,位置索引是0)。
这样RecyclerView会立刻渲染这一条目,不需要等待后续数据。比如你用AsyncTask的话,可以在onProgressUpdate方法里处理第一条数据的插入;如果用更现代的协程或者Flow,只要第一条数据一发射,就在主线程更新Adapter就行。
当然有办法!而且这才是处理大量数据(比如成千上万部电影)的正确姿势——绝对不能等全部数据下载完再一次性显示,不然用户要等很久,体验极差。
你提到的AsyncTask方案是可行的,但要注意不要每次都调用notifyDatasetChanged(),因为这个方法会刷新整个RecyclerView,性能开销大。正确的做法是:
- 在AsyncTask的
doInBackground里,每下载完一批数据(比如每次下载20部电影),就通过publishProgress()把这批数据传递到onProgressUpdate; - 在
onProgressUpdate中,把这批数据添加到Adapter的数据集列表里,然后调用notifyItemRangeInserted(startPosition, itemCount),其中startPosition是这批数据插入前列表的长度,itemCount是新增数据的数量。
举个简单的Adapter示例代码:
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.ViewHolder> { private List<Movie> mMovies = new ArrayList<>(); // ... 其他方法省略 public void addBatch(List<Movie> newMovies) { int startPosition = mMovies.size(); mMovies.addAll(newMovies); notifyItemRangeInserted(startPosition, newMovies.size()); } }
然后在AsyncTask的onProgressUpdate里调用adapter.addBatch(newMovies)就可以了。
另外提一句:现在AsyncTask已经被官方废弃了,推荐用协程+Flow或者RxJava来实现这种分批加载的逻辑,代码更简洁也更易维护,核心思路还是一样——每拿到一批数据就更新Adapter,用局部刷新的方法而不是全量刷新。
最后要注意:所有更新Adapter的操作必须在主线程执行,AsyncTask的onProgressUpdate本身就在主线程,协程的话记得切换到Dispatchers.Main。
内容的提问来源于stack exchange,提问作者Faizan Mubasher

