zoukankan      html  css  js  c++  java
  • RecyclerView使用databinding出现数据闪烁问题

    When something takes longer than expected, write it down.

     

    问题产生:

    最近做项目遇到RecyclerView使用databinding时,出现数据闪烁,老大说,这问题不解决就不要用databinding。。。

    闪烁图效果如下,点击Refresh,数据闪了一次:

    明明数据没变,但数据却刷了一遍。

    代码如下:

    class TestDBAdapter extends RecyclerView.Adapter<TestDBViewHolder> {
    
            private List<TestData> list;
    
            public TestDBAdapter(List<TestData> list) {
                this.list = list;
            }
    
            @Override
            public TestDBViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                ItemTestDbRecyclerViewBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.item_test_db_recycler_view, parent, false);
                return new TestDBViewHolder(binding);
            }
    
            @Override
            public void onBindViewHolder(TestDBViewHolder holder, int position) {
                holder.binding.setData(list.get(position));
    //            holder.binding.executePendingBindings();
            }
    
            @Override
            public int getItemCount() {
                return list.size();
            }
        }
    
        class TestDBViewHolder extends RecyclerView.ViewHolder {
            public ItemTestDbRecyclerViewBinding binding;
    
            public TestDBViewHolder(ItemTestDbRecyclerViewBinding binding) {
                super(binding.getRoot());
                this.binding = binding;
            }
    
            public TestDBViewHolder(View itemView) {
                super(itemView);
            }
        }
    }

     

    问题追踪:

    从图中可以看到item从浙江-->广东-->浙江,这个简单,因为recycler view会重用item,刷新时,第一个元素使用了第四个元素的ViewHolder。

    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
            if (holder instanceof TaskItemViewHolder) {
                final TaskItemViewHolder taskItemViewHolder = (TaskItemViewHolder) holder;
                LogUtils.d("before: "+taskItemViewHolder.getBinding().getData());//打印bind前holder中的数据
                taskItemViewHolder.bindTo(mList.get(position), position);
                LogUtils.d("after: "+mList.get(position)+" position:"+position);//打印当前item的数据
            }
        }
    

    打印结果:

    before: 广东

    after: 浙江 

    数据是肯定变了,难道数据闪烁是正常的,那为什么不用databinding时,没有出现数据闪烁现象?有人说全局刷新时layout重置。。。

    网上不是有好多demo吗?去看看别人怎么用的,看看别人的代码是否有问题,于是下了个demo https://github.com/jredthree/AllRecyclerDemo, 安装,运行,refresh,卧槽,居然没有闪烁!!!马上追踪代码,activity->adapter->onCreateViewHolder->onBindViewHolder。。。嗯?多了一行? holder.binding.executePendingBindings();这是what?没遇到过。加上这一行后,问题居然解决了。。。

    /**
    * Evaluates the pending bindings, updating any Views that have expressions bound to
    * modified variables. This <b>must</b> be run on the UI thread.
    */

    bindData后立即刷新!

    难道要立刻刷新?还没有搞清楚。。。

    问题解决:

      @Override
            public void onBindViewHolder(TestDBViewHolder holder, int position) {
                holder.binding.setData(list.get(position));
                holder.binding.executePendingBindings();//加一行,问题解决
            }    

    遗留问题:

    1. RecyclerView notifyDataChanged时,明明item的数据变化了,但为什么没有闪烁呢?

    2. executePendingBindings语句到底是什么用?调与不调有什么区别? 

     

     

  • 相关阅读:
    微软面试问题 情商测试
    SQL游标使用实例
    如何减小与“大牛”的差距
    Dotnet面试题
    排序算法对冒泡排序的优化改进算法
    一个SQL实现薪水大于所在部门平均薪水的员工
    ASP.NET中TextBox设置为Readonly后无法取值的解决办法
    jQuery.Autocomplete实现自动完成功能(详解)
    php发送get、post请求的几种方法
    ISO Latin1字符集
  • 原文地址:https://www.cnblogs.com/xiangxing/p/6371202.html
Copyright © 2011-2022 走看看