封装的Adapter的优缺点

本文探讨了个人封装的ListView Adapter与Google发布的标准Adapter在性能和代码简洁性上的对比。Google的Adapter优化了滑动速度,但代码量较大;个人封装的Adapter则简化了代码,但滑动流畅度降低。作者建议尽管代码量增加,但为了更好的用户体验,推荐使用Google的标准写法。分析指出,个人封装的Adapter可能因缓存整个item View导致内存占用过多,影响性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

个人封装的listView的Adapter封装类:
跟Google发布优化的标准Adapter写法对比优缺点:
Google发布标准版:优点是Adapter的滑动速度快,缺点是代码多了点
自己封装的Adapter类:优点是Adapter的滑动速度慢,优点是代码少写
比较是推荐Google标准写法(虽然代码多写了,但是流畅度好很多)
本人封装的listView的Adapter

public abstract class MyBaseAdapter<T> extends BaseAdapter {
    List<T> data;
    int layout;
    Context context;

    public MyBaseAdapter(Context context, @LayoutRes int layout, List<T> data) {
        this.data = data;
        this.layout = layout;
        this.context = context;
    }

    @Override
    public int getCount() {
        if (data == null) {
            return 0;
        }
        return data.size();
    }

    public void setDataChange(List<T> data) {
        this.data = data;
        this.notifyDataSetChanged();
    }
    @Override
    public T getItem(int position) {
        this.notifyDataSetChanged();
        return data.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    //convertView 划出屏幕的view对象
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        long startTime = System.nanoTime();
        Holder holder = null;
        if (convertView == null) {
            convertView = View.inflate(context, layout, null); //需要一个静态的Holder
            holder = new Holder(convertView);
            convertView.setTag(holder);
        }else {
            holder = (Holder) convertView.getTag();  //不能使用静态内部类,不然全是同样的视图
        }
        dataAndView(holder,getItem(position));
        long endTime = System.nanoTime();
        LogUtil.e("getView==="+(endTime-startTime));//测试用时多少
        return convertView;
    }

    protected abstract void dataAndView(Holder holder, T item);


    protected static class Holder {
        View rootView;
        SparseArray<View>  viewList = new SparseArray();//这里不能用static修饰,会出现问题
        public Holder(View rootView) {
            this.rootView = rootView;
        }
        public View getView(int viewId) {
            if (viewList.get(viewId)!=null) {
                return viewList.get(viewId);
            }else {
                View itemView = rootView.findViewById(viewId);
                viewList.put(viewId, itemView);
                return itemView;
            }
        }
        public TextView setTxetView(int viewId,String content) {
            TextView textView= (TextView) getView(viewId);
            textView.setText(content);
            return textView;
        }
    }
}

用法

MyBaseAdapter adapter = new MyBaseAdapter<DomeBean>(getActivity(), R.layout.fragment_work_log_item, list) {
                @Override
                protected void dataAndView(Holder holder, DomeBean bean) {
                    //写你具体需求
                    holder.setTxetView(R.id.test, bean.getName());
                }
            };
            listView.setAdapter(adapter);

这样封装对你写的adapter非常方便,不用去每个adapter对应一个holder,你不用写holder.
但是这样写测试流畅度和原生的adapter标准写法差的不是一星半点,卡的不行,也有可能是本人封装的不行
只好放弃这种封装,使用以下封装: 但是还是要做的是每个adapter对应一个Holder.

public abstract class MyListAdapter<T> extends BaseAdapter {
    private List<T> list;
    public MyListAdapter(List<T> list){
        this.list = list;
        if (this.list == null)
            this.list = new ArrayList<>();
    }

    public void setList(List<T> list) {
        this.list = list;
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public Object getItem(int i) {
        return list.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }
    @Override
    public View getView(int position, View view, ViewGroup viewGroup) {
        return viewAndData(position,view,viewGroup,list);
    }
    public abstract View viewAndData(int position, View view, ViewGroup viewGroup,List<T> list);
}

用法:

MyListAdapter<WorkLogBean> adapter = new MyListAdapter<WorkLogBean>(list) {
            @Override
            public View viewAndData(int position, View view, ViewGroup viewGroup, List list) {//这里写的就是Google推荐的,就是BaseAdapter的getView写法一样,在里面写具体代码

                return view;
            }
        };
         listView.setAdapter(adapter);

这跟原来没封装的差不了多少,就是为了不用每个listView对应每个Adapter的写法

来分析下为什么上面封装的adapter流畅度不行:
上面封装的是采取了缓存一个rootView 一个双列集合,通过id找item中的view, 设置不同属性
Google推荐的adapter里面的Holder写法是(个人模板):

   static class ViewHolder {
        public ViewHolder(View v) {
            workIdTv = (TextView) v.findViewById(R.id.work_id_tv);
            dateTv = (TextView) v.findViewById(R.id.date_tv);
            timeTv = (TextView) v.findViewById(R.id.time_tv);
            stateTv = (TextView) v.findViewById(R.id.state_tv);
            itemLayout = (LinearLayout) v.findViewById(R.id.item_layout);
            starIv = (ImageView) v.findViewById(R.id.iv_star);
        }
        private TextView workIdTv, dateTv, timeTv, stateTv;
        private ImageView starIv;
        private LinearLayout itemLayout;

    }

它只缓存各个item中的view —>缓存了一个view的骨架没有缓存整个View,相当于上面的双列集合的缓存
所以推测是上面由于多缓存一个整体的item View,由于在一开始可见的时候,Holder会生成多个itemView,有可能是缓存itemView造成内存多,分配的计算资源少而造成的.如有更好的答案或更好的分析请留言

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值