默认是在一个fragment中实现RecyclerView.

private inner class CrimeAdapter() :
ListAdapter<Crime, CrimeHolder>(mDiffCallback) { override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): CrimeHolder {//这个parent就是RecyclerView;在这个方法中绑定子项视图
val view = layoutInflater.inflate(
R.layout.fragment_crime_list_item,
parent,
false
)//负责创建要显示的视图,并封装到ViewHolder里
return CrimeHolder(view)
} override fun onBindViewHolder(
holder: CrimeHolder,
position: Int
) {//负责将数据集里指定位置的crime数据发送给指定的ViewHolder
val crime = currentList[position]
holder.bind(crime)//把viewholder和adapter的处理逻辑分开,只需调用viewholder的方法
} }
  1. 构造函数里也不需要传一个list了,在onBindViewHolder里原来是list[position],现在可以用currentList。这个字段是ListAdapter里面的。之前我的一个bug就是这个B弄的。
  2. 继承自ListAdapter, <模型类, 自定义holder>, 参数需要一个DiffUtil.ItemCallback<Crime>()实例,可以在这个fragment里以伴随类的方式定义。
    companion object {
    val mDiffCallback = object : DiffUtil.ItemCallback<Crime>() {//作为ListAdapter的参数
    override fun areItemsTheSame(oldItem: Crime, newItem: Crime): Boolean {
    return oldItem.id == newItem.id
    } override fun areContentsTheSame(oldItem: Crime, newItem: Crime): Boolean {
    return oldItem.title == newItem.title
    }
    }

    必须实现这两个方法,第一个方法检测item是否相同,第二个检测item内容是否相同。这两个方法都很重要。第二个方法如果比较的item的属性不对,更新会有延迟!!比如说比较的是id,那我更改了title,我回到列表界面时,他判断我的id没变,所以内容没变,结果他不给我更新我操他妈的。上面那个写法也是不完整的,只比较了title,那我更改了其他信息,回到主界面也是不会立即更新的,会有一个延迟。

  3. 重头戏!!!那如何提交recycleview列表的更新呢?首先在fragment字段中定义一个adapter, 然后让recyclerview的adapter字段指向这个adapter, 然后因为传进去的列表是livedata,所以我们用observe检测数据变化,一有变化就用ListAdapter里的方法——submitList来提交,到这里就明白了,我们取消了原来以参数的方式传列表进去,改为submitList.(更删改查都用它,反正有变化就用它)
    private var mAdapter: CrimeAdapter = CrimeAdapter()
    override fun onCreateView(//onCreateview方法里不用做什么和本文相关的事,看下面
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
    ): View {
    _binding = FragmentCrimeListBinding.inflate(inflater, container, false)
    binding.crimeRecyclerview.layoutManager =
    LinearLayoutManager(context)//把加载的recyclerview视图的布局设为线性布局
    return binding.root
    }
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState) binding.crimeRecyclerview.adapter = mAdapter//
    crimeListViewModel.crimeListLiveData.observe(
    viewLifecycleOwner,
    { crimes ->
    crimes?.let {
    mAdapter.submitList(crimes)//有更新就提交给adapter
    }
    }
    )
    }
  4. 注意!!传给submitList的列表不能是同一个列表引用,如果是同一个列表引用的话要拷贝一份,
    新拿到的数据根本没有更新到列表中来。问题可能出在 submitList() 方法上:
    
    public void submitList(@Nullable List<T> list) {
    mDiffer.submitList(list);
    } 最终调用的是 AsyncListDiffer 类中的 submitList() 方法: public void submitList(@Nullable final List<T> newList,
    @Nullable final Runnable commitCallback) {
    // incrementing generation means any currently-running diffs are discarded when they finish
    final int runGeneration = ++mMaxScheduledGeneration;
    if (newList == mList) {
    // nothing to do (Note - still had to inc generation, since may have ongoing work)
    if (commitCallback != null) {
    commitCallback.run();
    }
    return;
    }
    final List<T> previousList = mReadOnlyList;
    // fast simple remove all
    if (newList == null) {
    //noinspection ConstantConditions
    int countRemoved = mList.size();
    mList = null;
    mReadOnlyList = Collections.emptyList();
    // notify last, after list is updated
    mUpdateCallback.onRemoved(0, countRemoved);
    onCurrentListChanged(previousList, commitCallback);
    return;
    }
    // fast simple first insert
    if (mList == null) {
    mList = newList;
    mReadOnlyList = Collections.unmodifiableList(newList);
    // notify last, after list is updated
    mUpdateCallback.onInserted(0, newList.size());
    onCurrentListChanged(previousList, commitCallback);
    return;
    }
    final List<T> oldList = mList;
    // 省略一些代码。
    } 第一次我们调用 submitList() 方法时,把成员变量集合 list 传递过来,那么 newList 参数就不为 null,在第 25 行,会进入 if 语句,把 newList 赋值给 mList,也就是把 list 赋值给 mList。 第二次我们调用submitList() 方法时,仍是把成员变量集合 list 传递过来,这时 mList 就是指向的 list,所以第 5 行的 if (newList == mList) 成立,进而直接 return 掉 submitList() 方法。新的数据并未更新到列表中。

    因为livedata的observe传给我们的不是同一个列表引用,所以可以直接放进去submitList.

最后加上一份官方的示例代码

A complete usage pattern with Room would look like this:
* <pre>
* {@literal @}Dao
* interface UserDao {
* {@literal @}Query("SELECT * FROM user ORDER BY lastName ASC")
* public abstract LiveData&lt;List&lt;User>> usersByLastName();
* }
*
* class MyViewModel extends ViewModel {
* public final LiveData&lt;List&lt;User>> usersList;
* public MyViewModel(UserDao userDao) {
* usersList = userDao.usersByLastName();
* }
* }
*
* class MyActivity extends AppCompatActivity {
* {@literal @}Override
* public void onCreate(Bundle savedState) {
* super.onCreate(savedState);
* MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class);
* RecyclerView recyclerView = findViewById(R.id.user_list);
* UserAdapter&lt;User> adapter = new UserAdapter();
* viewModel.usersList.observe(this, list -> adapter.submitList(list));/////////直接用行了
* recyclerView.setAdapter(adapter);
* }
* }
*
* class UserAdapter extends ListAdapter&lt;User, UserViewHolder> {
* public UserAdapter() {
* super(User.DIFF_CALLBACK);
* }
* {@literal @}Override
* public void onBindViewHolder(UserViewHolder holder, int position) {
* holder.bindTo(getItem(position));
* }
* public static final DiffUtil.ItemCallback&lt;User> DIFF_CALLBACK =
* new DiffUtil.ItemCallback&lt;User>() {
* {@literal @}Override
* public boolean areItemsTheSame(
* {@literal @}NonNull User oldUser, {@literal @}NonNull User newUser) {
* // User properties may have changed if reloaded from the DB, but ID is fixed
* return oldUser.getId() == newUser.getId();
* }
* {@literal @}Override
* public boolean areContentsTheSame(
* {@literal @}NonNull User oldUser, {@literal @}NonNull User newUser) {
* // NOTE: if you use equals, your object must properly override Object#equals()
* // Incorrectly returning false here will result in too many animations.
* return oldUser.equals(newUser);
* }
* }
* }</pre>

如何正确地使用RecyclerView.ListAdapter的更多相关文章

  1. WanJetpack项目:用Jetpack实现玩Android,追求最官方的实现方式

    项目简介 玩Android demo.用Jetpack MVVM开发架构.单Activity多Fragment项目设计,项目结构清晰,代码简洁优雅,追求最官方的实现方式.用到以下知识点: LiveDa ...

  2. Android RecyclerView使用ListAdapter高效刷新数据

    原文:Android RecyclerView使用ListAdapter高效刷新数据 - Stars-One的杂货小窝 我们都知道,当RecyclerView数据源更新后,还需要通过adapter调用 ...

  3. RecyclerView添加Header的正确方式

    原文链接:http://blog.csdn.net/qibin0506/article/details/49716795 看了一下博客目录,已经有好几篇博客是关于RecyclerView的,不过对于这 ...

  4. <Android 基础(三十五)> RecyclerView多类型Item的正确实现姿势

    简介 RecyclerView是我们开发过程中经常使用到的一个元素,原生的RecyclerView.Adapter基本上可以满足一般的需求,关于RecyclerView的基础介绍请移步: Recycl ...

  5. 【Android】【踩坑日记】RecyclerView获取子View的正确姿势

    开发过程中发现RecyclerView.getChildAt(position)为空的情况,但是明明这个position却没有越界. 解决办法:用recycler.getLayoutManager() ...

  6. Android 高级UI设计笔记07:RecyclerView 的详解

    1. 使用RecyclerView       在 Android 应用程序中列表是一个非常重要的控件,适用场合非常多,如新闻列表.应用列表.消息列表等等,但是从Android 一出生到现在并没有非常 ...

  7. Android RecyclerView体验(一)- 简介

    在网上关于RecyclerView的基本使用方式已经有了比较详细介绍,而且其设计结构也类似于ListView,所以本文将不重点介绍如何使用,在文末的引用中都可以相关内容.这里主要是介绍Recycler ...

  8. RecyclerView使用大全

    RecylerView介绍 RecylerView是support-v7包中的新组件,是一个强大的滑动组件,与经典的ListView相比,同样拥有item回收复用的功能,这一点从它的名字recyler ...

  9. 带你实现开发者头条APP(五)--RecyclerView下拉刷新上拉加载

    title: 带你实现开发者头条APP(五)--RecyclerView下拉刷新上拉加载 tags: -RecyclerView,下拉刷新,上拉加载更多 grammar_cjkRuby: true - ...

随机推荐

  1. linux gcc命令参数

    gcc命令参数笔记 1. gcc -E source_file.c -E,只执行到预处理.直接输出预处理结果. 2. gcc -S source_file.c -S,只执行到汇编,输出汇编代码. 3. ...

  2. 前端数据渲染及mustache模板引擎的简单实现

    早期数据渲染的几种方式 在模板引擎没有诞生之前,为了用JS把数据渲染到页面上,诞生了一系列数据渲染的方式. 最最基础的,莫过于直接使用DOM接口创建所有节点. <div id="roo ...

  3. sublimeText常用插件

    扩展包: EmmetAlignmentDoc​BlockrSideBarEnhancementsFileDiffsColorsublimelocalizationAutoFileNameA File ...

  4. 【Springboot】Springboot监听器Demo

    /** * @author: yq * @date: 2020/8/31 0:01 * @description 自定义事件 */ @Data public class MyEvent extends ...

  5. git pull 默认拉取远端其他分支 问题解决

    今天工作中遇见了一个问题:执行git pull 命令时,默认合并了远端的某个分支,经过查阅资料发现是git的配置问题. 如图所示: git 查看远端主机详细配置信息 git remote show o ...

  6. poj2112 二分最大流+Floyd

    题意:      一个农场主有一些奶牛,和一些机器,每台机器有自己的服务上限,就是一天最多能给多少头奶牛挤奶,给你任意两点的距离,问你让所有的奶牛都被挤奶时,奶牛于机器最远距离的最近是多少. 思路: ...

  7. Shodan的使用

    目录 Shodan Shodan工作原理 Shodan的使用 使用搜索过滤 Kali中安装 Shodan Kali中Shodan的使用 Shodan Shodan 是一个搜索引擎,但它与 Google ...

  8. 如何以最简单的方式安装 KALI 渗透测试框架系统

    0x01 第一步下载 KALI 百度搜索 KALI 官网,找到下载区,我选的是 64 位标准版,但是推荐下载 32 位(功能貌似更全) 这个为下载后的 iso 镜像文件 0x02 第二步打开虚拟机,配 ...

  9. MS06-040漏洞研究(下)【转载】

    课程简介 经过前两次的分析,我们已经对Netapi32.dll文件中所包含的漏洞成功地实现了利用.在系统未打补丁之前,这确实是一个非常严重的漏洞,那么打了补丁之后,这个动态链接库是不是就安全了呢?答案 ...

  10. Web中的相对路径和绝对路径

    前台路径:浏览器端发起的资源请求路径 后台路径:服务器端发起的资源请求路径