安卓Adapter去item重复使用的方案!

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了安卓Adapter去item重复使用的方案!相关的知识,希望对你有一定的参考价值。

关于adapter去重复的问题其实是个很简单的问题,很多人没有理解到list,grid以及recyclerview重复利用item以及使用
viewholder的原理,所以在去重的道路上走得很坎坷,在这里小羽带着大家去好好的学习和总结一下item的知识,
然后使用十分简洁的方案去有效的解决重复使用item带来的问题。
1.认识item的重复使用和viewholder的出现。
    item的重复使用目的是为了解决大量的list数据消耗大量的视图空间,而viewholder的出现是系统在解决数据显示的时候做的一种方案。
    而这种方案主要针对的是重复的item但是数据不同。通过tag去绑定在item上然后再取得使用。
    保证了每个已经创建的item上一定有个viewholder,所以每次刷新item的时候都必须要把数据和各种状态绑定一遍,
    否则滑动的时候就会有重复显示的问题。
2.从系统原理上去去重复。
    上面我们讲了item通过viewholder去解决数据重复的方案,虽然有点繁琐,但是有效可行。
    有人要问:“如果我想改变某个item的属性又不想重复使用导致其他item属性也改变,什么办法好用呢?”。
    这个问题最近的项目里我也遇到了。而且是一个item里面有两个子item,这两个子item也要一摸一样,但是不能同时干扰。
    需要做属性动画去改变样式!!(是不是很蛋疼?毕竟公司想要炫酷,那我们就按需设计呗!)。
    既然item重复利用,那么item的子控件都会是同一个对象。
    所以小羽滋生了一种想法,既然控件是一样的,那么我可以记录一个当前选中的item或者它的一个控件,
    如果是当前item并且对应的position也是一样的,那么肯定是当前的item可以做改变,
    当滑动到重复利用的item时,虽然也是当前的item但是position却不一样,所以这时候就做默认的设置。
    当滑回来的时候满足前面的条件所以又会继续改变。为什么可以这么自信的使用这种方案?原因很简单。
    系统在重复利用item的时候是做过处理的,重复利用的这个item不可能和上个item同时出现在屏幕上。
    所以我们不需要像viewholder一样把每种状态都做改变,因为即使此刻的上一个item的属性会随着当前item属性改变而改变,
    放心你是看不见的,所以我们不必担心这种方案的不可行!
3源码分析。
//recyclerview的adapter开始BindViewHolder
@Override
public void onBindViewHolder(RecViewHolder holder, final int position) {
    if(!Utils.listIsEmpty(mTopPaymentTypes) && mTopPaymentTypes.size() > position){
        PaymentType topPaymentType = mTopPaymentTypes.get(position);
        initPayBtnResource(holder.topPayViewItem, position, topPaymentType);
    }

    if(!Utils.listIsEmpty(mBottomPaymentTypes) && mBottomPaymentTypes.size() > position){
        PaymentType bottomPaymentType = mBottomPaymentTypes.get(position);
        initPayBtnResource(holder.bottomPayViewItem, position,bottomPaymentType);
    }
}

//设置item数据
private void initPayBtnResource(View itemView, int position, PaymentType paymentType) {
    TextView payTypeName = (TextView) itemView.findViewById(R.id.payview_item_name);
    ImageView payTypeImage = (ImageView) itemView.findViewById(R.id.payview_item_image);
    View payTypeLight = itemView.findViewById(R.id.payview_item_light);
    PayTypeSource paySource = mPaySources.get(paymentType);
    if (paySource != null) {
        payTypeName.setText(paySource.getPayTypeName());
        //viewholder绑定item数据
        bindItemData(View itemView, int position, PaymentType paymentType);

        //下面这段语句就是解决item重复使用修改属性导致其他item出现问题的方案。
        if (mCheckedPayType == paymentType) {
            startLightAnimator();
            mAnimPayLight = payTypeLight;
        } else {
            if (mAnimPayLight == payTypeLight) {
                endLightAnimator();
            }
        }
    }

    if (isSinglePay) {
        itemView.setOnClickListener(null);
        itemView.setBackgroundResource(R.drawable.pay_item_uncheck);
    } else {
        itemView.setOnClickListener(mClick);
        itemView.setTag(paymentType);
        itemView.setBackgroundResource(R.drawable.pay_item_can_change);
    }
}

4.总结该方案!
    这个方案只在单个item重复使用的时候才会被调用做改变,不需要每个item都去改变属性来保持平衡,
    非常简单直观的解决的重复利用的问题,从代码的简洁和系统执行的效率上说,都比较优,缺点就是多占了一个引用的内存,
    性价比上来说非常的靠谱。
    有人肯定要问后面的endLightAnimator();只结束了动画但是属性还是变了。
    这里小羽不得不吐槽一句了:“每个人的项目需求不一样,我这里是浮光效果,不选中的时候我可以直接把浮光隐藏掉就行了,至于这个属性在那个位置都不重要了”。
    那么如果是一定要显示的去改变属性呢?这个小羽在3里面就说了,默认属性,就是比如你贴了一个机器人,
    要把他变成瘦机器人,那么这里end的时候直接赋值一个原来的机器人.方案是对的,
    问题是解决问题的需求不一样大家要按照自己的需求去实现。
    原谅小羽不能贴出所有代码(虽然代码是自己写的,但是作为公司商业化产品,部分保密还是需要的)。

以上是关于安卓Adapter去item重复使用的方案!的主要内容,如果未能解决你的问题,请参考以下文章

如何在安卓开发中实现对listview的增删改查与刷新

安卓中adapter的应用

Android 怎么删除list中的某一项item

Android Adapter代码片

Arrayadaper在安卓开发中的作用

Adapter的封装之路