美文网首页
Android ListAdapter 使用详解 (Java &

Android ListAdapter 使用详解 (Java &

作者: 虞_18bd | 来源:发表于2020-12-28 22:09 被阅读0次

    ListAdapter

    第一次发现这个适配器要从google的经典demo sunflower说起了。

    如何让Adapter简洁且优雅(其实很多人都在致力于给Adapter减负,作为一个适配器,它要调节View和数据的关联,导致它需要维护一整套视图的同时又要维护一系列的数据),经典的像是BRVAH。他其实已经做的很好了,里面包含了很多常用的场景,具体的话我以后再介绍。

    回到ListAdapter,直接看如何使用不bb


    kotlin

    Fragment / Activity

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val binding = FragmentPlantListBinding.inflate(inflater, container, false)
        context ?: return binding.root
    
        val adapter = PlantAdapter()  // 1.为什么这里把adapter作为方法中的变量?
        binding.plantList.adapter = adapter // 2.数据怎么绑定上的?
        subscribeUi(adapter)// 3.怎么更新数据?
        return binding.root
    }
    
    private fun subscribeUi(adapter: PlantAdapter) {
        viewModel.plants.observe(viewLifecycleOwner) { plants ->
            adapter.submitList(plants)
        }
    }
    

    上面这段kotlin代码第一次用ListAdapter的人肯定会有这样的疑问:

    除去里面使用databinding和LiveData这里不进行详细说明,前者只是为了视图的绑定,后者则是一个典型的观察者模式实现数据的更新。

    1. 这里直接给结论,之前Adapter在更新数据时,需要手动调用notifyDataSetChanged方法,实现以数据驱动的视图刷新,并且需要手动管理Adapter中的数据集合,而ListAdapter中使用了AsyncListDiffer,让数据管理更加轻松。

    2. 通过submitList来进行数据绑定

    3. 数据更新也通过submitList(这里你肯定会问,每次都submitList是不是会影响效率)

      AsyncListDiffer 的作用

      直接上Adapter代码

      class PlantAdapter : ListAdapter<Plant, RecyclerView.ViewHolder>(PlantDiffCallback()) {
      
          override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):       RecyclerView.ViewHolder { // 初始化ViewHolder
              return PlantViewHolder(
                  ListItemPlantBinding.inflate(
                      LayoutInflater.from(parent.context),
                      parent,
                      false
                  )
              )
          }
      
          override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
              val plant = getItem(position) // 直接通过getItem获取数据
              (holder as PlantViewHolder).bind(plant)// 绑定视图和数据
          }
      
          class PlantViewHolder(
              private val binding: ListItemPlantBinding
          ) : RecyclerView.ViewHolder(binding.root) {
      
              }
      
              fun bind(item: Plant) { // 绑定方法
                  binding.apply {
                      plant = item  
                      executePendingBindings()  // 注意: 这个方法不调用可能导致item闪烁
                  }
              }
          }
      }
      
      private class PlantDiffCallback : DiffUtil.ItemCallback<Plant>() {
      
          override fun areItemsTheSame(oldItem: Plant, newItem: Plant): Boolean {
              return oldItem.plantId == newItem.plantId // 通过id判断是否是相同的item
          }
      
          override fun areContentsTheSame(oldItem: Plant, newItem: Plant): Boolean {
              return oldItem == newItem  // 通过对象判断是否是相同的Content
          }
      }
          
      
      

    这里出现了PlantDiffCallback,这又是做什么的呢,我们再回到submitList源码中

    @Override
    public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
        T oldItem = oldList.get(oldItemPosition);
        T newItem = newList.get(newItemPosition);
        if (oldItem != null && newItem != null) {
            return mConfig.getDiffCallback().areItemsTheSame(oldItem, newItem);
        }
        // If both items are null we consider them the same.
        return oldItem == null && newItem == null;
    }
    
    @Override
    public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
        T oldItem = oldList.get(oldItemPosition);
        T newItem = newList.get(newItemPosition);
        if (oldItem != null && newItem != null) {
            return mConfig.getDiffCallback().areContentsTheSame(oldItem, newItem);
        }
        if (oldItem == null && newItem == null) {
            return true;
        }
        // There is an implementation bug if we reach this point. Per the docs, this
        // method should only be invoked when areItemsTheSame returns true. That
        // only occurs when both items are non-null or both are null and both of
        // those cases are handled above.
        throw new AssertionError();
    }
    

    源码就是通过之前的回调,去判断哪些item需要替换,哪些item不需要

    相关文章

      网友评论

          本文标题:Android ListAdapter 使用详解 (Java &

          本文链接:https://www.haomeiwen.com/subject/locxoktx.html