美文网首页
由NotifyDateSetChanged无法生效产生的思考

由NotifyDateSetChanged无法生效产生的思考

作者: Rreply | 来源:发表于2018-07-22 01:02 被阅读12次

最近在使用notifyDataSetChanged方法时,发现数据并没有按照想象中的刷新,经过查看文档以及搜索,得知了产生这种现象的原因。

 if (mCountDownAdapter == null) {
            mCountDowns = LitePal.findAll(CountDown.class);
            mCountDownAdapter = new CountDownAdapter(mCountDowns);
            mRecyclerView.setAdapter(mCountDownAdapter);
        } 

首先Litepal.findAll方法最终调用了如下onFindAll方法

public <T> List<T> onFindAll(Class<T> modelClass, boolean isEager, long... ids) {
        List<T> dataList;
        if (isAffectAllLines(ids)) {
            dataList = query(modelClass, null, null, null, null, null, "id", null,
                    getForeignKeyAssociations(modelClass.getName(), isEager));
        } else {
            dataList = query(modelClass, null, getWhereOfIdsWithOr(ids), null, null, null, "id",
                    null, getForeignKeyAssociations(modelClass.getName(), isEager));
        }
        return dataList;
    }

可以看出Litepal.findAll最终返回的List是根据查询的数据添加到List中返回的,也就是说如果数据库发生了变化,那么这个List是不会变化的。这就为我们理解RecycleView为什么不能正确刷新打下了基础。

mCountDownAdapter = new CountDownAdapter(mCountDowns);

在这里,Adapter是和mCountDowns连接起来的,mCountdowns就是返回的List。因此在Adapter没有重建的时候,它绑定的都是mCountdowns列表。
在用户输入数据的时候,我是进行下面处理的:

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                mCountDown.setName(s.toString());
                mCountDown.save();    //将CountDown实例产生的变化存储到数据库中
            }

因此,我处理数据变化是方式是直接在数据库中进行修改,而与Adapter绑定的List却不会发生变化。所以Adapter调用NotifyDateSetChanged的时候就不会刷新数据了,因为其绑定的List数据没有刷新。
因此,有两个方法可以解决这个问题,一种是在修改数据到数据库的同时,对Adapter相关联的List也进行修改。一种是将关联的List重新清空,获取数据。从对性能的损失上来看,第一种方法较好。
有时候修改的只是一个item中的数据,而调用NotifyDateSetChanged的时候确实把全部可见项的数据都刷新了,造成了不必要的性能损失。
使用NotifyItemChanged(int position)方法就能够很好地避免这种损失,可以创建一个全局变量来储存点击的位置。

        @Override
        public void onClick(View v) {
            int countdown_id = mCountDown.getId();
            Intent intent = DetailActivity.newIntent(getActivity(), countdown_id);
            startActivity(intent);
            position = getAdapterPosition();   //获取该位置
        }

然而到这里还不算完成,NotifyItemChanged(int position)方法刷新的是这个item中所有的View,不管其有没有被修改。这就导致一个问题,如果这个item中存在很多耗时的动画图片等,刷新这些view就会耗费大量的时间。
举个例子,我刷微博的时候,看到一个博主发的gif太搞笑了,点了一个赞,如果整个item都刷新的话,这个gif也要重新刷新,这就太浪费时间了。
因此使用notifyItemChanged(int position, Object payloads)方法,首先需要重写如下方法

        @Override
        public void onBindViewHolder(ViewHolder holder, int position, List<Object> payloads) {
              //因为payloads为空时,默认刷新item中全部的view,所以需要这样写
            if(!payloads.isEmpty()) {
                if (payloads.get(0) instanceof Integer) {
                    holder.tvScore.setText(String.valueOf((Integer)payloads.get(0)))
                }
            }else {
                super.onBindViewHolder(holder,position, payloads);
            }
        }

最后在需要刷新数据的时候调用notifyItemChanged(int position, Object payloads)就行了。

相关文章

  • 由NotifyDateSetChanged无法生效产生的思考

    最近在使用notifyDataSetChanged方法时,发现数据并没有按照想象中的刷新,经过查看文档以及搜索,得...

  • 由"我"产生的思考

    几年就看了《新世界灵性的觉醒》,最近突然有一股冲动要去将这本书的视频内容,录成文字版。在录的过程中。我也回顾了Ec...

  • 由失落的豆瓣“小事”产生的思考

    前几天豆瓣进行了一次大的改版,与以往不同的是,这次改版更像是回到了最初豆瓣的感觉。用户大多也是积极的评价。 比较明...

  • 由离家产生对工作的思考

    今天再次踏上了离家之路,父母送我们到车上,我又送父母出站,虽不是第一次离家,可分明母亲的眼角还是红了……...

  • 由pokemongo热产生的非常简单思考

    老牌游戏巨人任天堂公司最近靠PokemonGo手游又焕发了青春,而且让人发现还是那么“美貌如花”。从网上的信息可知...

  • 17.5.6 小波FansArea(动画)学习笔记

    ⁃按钮前景色,背景色的区别,注:Type==custom时前景色(tint)无法生效 ⁃IB产生图片圆角(运行时参...

  • 2018-05-14

    合理规划时间,时间产生效益。

  • 秩序产生效率

    检票口a:队伍排得老长了,人挨着人,活像一条条黑黢黢的大蟒蛇。 检票口b:队伍长度只有检票口a的一半,可是,一条队...

  • 布局产生效益

    有组织的少数,胜过无组织的多数。这就是依靠规划和管理产生效益的根本原理。 无规划无管理的生活,就会乱糟糟,无端消耗...

  • PathFilter无法生效

    最近再写一个MapReduce的时候出现了一个诡异的问题, PathFilter无法生效, 具体描述如下: 代码参...

网友评论

      本文标题:由NotifyDateSetChanged无法生效产生的思考

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