Android BaseAdapter和ViewHolder 优化

首先赞下hyman大神

以前只是简单的重写个BaseAdapter,将getView方法保持抽象。而ViewHolder没有抽象过。。。

ViewHolder (用了一个集合+泛型管理存取view)

/**
 * author : stone
 * email  : [email protected]
 * time   : 15/7/24 14 27
 */
public class StoneViewHolder {

    private int mPosition;
    private View mConvertView;
    private SparseArray<View> mViews;  //管理listView-item中的view

    public StoneViewHolder(Context context, int layoutId, int position, ViewGroup parent) {
        this.mPosition = position;

        this.mConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false);
        this.mConvertView.setTag(this);

        this.mViews = new SparseArray<View>();
    }

    public View getConvertView() {
        return mConvertView;
    }

    public static StoneViewHolder getInstance(Context context, int layoutId, int position, View
            convertView, ViewGroup parent) {
        if (convertView == null) {
            return new StoneViewHolder(context, layoutId, position, parent);
        } else {
            StoneViewHolder holder = (StoneViewHolder) convertView.getTag();
            holder.mPosition = position;  //更新复用的convertView中  position
            return holder;
        }
    }

    public <T extends View>  T getView(int viewId) {
        View view = mViews.get(viewId);
        if (view == null) {
            view = mConvertView.findViewById(viewId);
            mViews.put(viewId, view);
        }
        return (T) view;
    }

    public <T> void setTag(int viewId, T tag) {
        getView(viewId).setTag(tag);
    }

    public <T> T getTag(int viewId) {
        return (T) getView(viewId).getTag();
    }

    /*------------------------  设置view属性(以后扩展) --------------------------------*/

    public StoneViewHolder setText(int viewId, String text) {
        ((TextView)getView(viewId)).setText(text);
        return this;
    }

    public StoneViewHolder setText(int viewId, int resId) {//R.string.
        ((TextView)getView(viewId)).setText(resId);
        return this;
    }

    public StoneViewHolder setImageBitmap(int viewId, Bitmap bitmap) {
        ((ImageView)getView(viewId)).setImageBitmap(bitmap);
        return this;
    }

    public StoneViewHolder setImageResource(int viewId, int resId) {
        ((ImageView)getView(viewId)).setImageResource(resId);
        return this;
    }
}

Adapter

/**
 * author : stone
 * email  : [email protected]
 * time   : 15/7/24 14 46
 */
public abstract class StoneListAdapter<T> extends BaseAdapter {

    private List<T> mData;
    private Context mContext;
    private int mLayoutID;

    public StoneListAdapter(Context context, int layoutID, List<T> data) {
        this.mContext = context;
        this.mLayoutID = layoutID;
        this.mData = data == null ? new ArrayList<T>() : data;
    }

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

    @Override
    public T getItem(int position) {
        return mData.get(position);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        StoneViewHolder holder = StoneViewHolder.getInstance(mContext, mLayoutID, position,
                convertView, parent);

        getView(mContext, holder, position);

        return holder.getConvertView();
    }

    protected abstract void getView(Context context, StoneViewHolder holder, int position);

}

在ListViewActivity中使用

stoneBaseAdapter = new StoneListAdapter<User>(ListViewActivity.this, R.layout.activity_listview_item, mData) {

    @Override
    protected void getView(Context context, final StoneViewHolder holder, final int position) {
        User user = getItem(position);

        holder.setText(R.id.tv_id, user.getId()).setText(R.id.tv_name, user.getName())
                .setText(R.id.tv_age, user.getAge() + "");

        holder.getView(R.id.btn_test).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });

    }
};

关于Adapter中View抢焦点:

如果 listView.setOnItemClickListener(listener);   且item中的  button.setOnClickListener(listener);

不管怎么点击,button会一直被触发...

只需要在item的root-layout中 添加 一个属性:   android:descendantFocusability="blocksDescendants"

关于item-view复用后,显示混乱:

有时条目过多,滑动到下一屏数据时,有些view复用后,view的状态(比如CheckBox的选种状态,ImageView的图片重复出现)会变乱。

一般处理呢,需要有一个机制,来管理一种对应关系: 当前position对应哪种状态

比如说checkBox选中状态混乱:

class MyAdapter extends StoneListAdapter<User> {
        private SparseBooleanArray mCheckStateArray;

        public MyAdapter(Context context, int layoutID, List data) {
            super(context, layoutID, data);
            this.mCheckStateArray = new SparseBooleanArray();
        }

        public void setChecked(int position, boolean isChecked) {
            mCheckStateArray.put(position, isChecked);
        }

        public boolean isChecked(int position) {
            return mCheckStateArray.get(position);
        }

        @Override
        protected void getView(Context context, final StoneViewHolder holder, final int position) {

            CheckBox cb = holder.getView(R.id.cb_check);
            cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    setChecked(position, isChecked);//记录状态,防缓存显示
                }
            });
            cb.setChecked(isChecked(position));
        }
    }

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-11 10:43:15

Android BaseAdapter和ViewHolder 优化的相关文章

Android BaseAdapter和ViewHolder 优化 解决ListView的item抢焦点问题和item错乱问题

首先赞下hyman大神 曾经仅仅是简单的重写个BaseAdapter,将getView方法保持抽象.而ViewHolder没有抽象过. .. ViewHolder (用了一个集合+泛型管理存取view) /** * author : stone * email : [email protected] * time : 15/7/24 14 27 */ public class StoneViewHolder { private int mPosition; private View mConve

Android中利用ViewHolder优化自定义Adapter的典型写法

public class MarkerItemAdapter extends BaseAdapter { private Context mContext = null; private List<MarkerItem> mMarkerData = null; public MarkerItemAdapter(Context context, List<MarkerItem> markerItems) { mContext = context; mMarkerData = mark

[Android]对BaseAdapter中ViewHolder编写简化(转)

来自博客:http://www.cnblogs.com/tiantianbyconan/p/3642849.html 在Android项目中,经常都会用到ListView这个控件,而相应的Adapter中getView()方法的编写有一个标准的形式,如下: 1 @Override 2 public View getView(int position, View convertView, ViewGroup parent) { 3 ViewHolder holder; 4 if(null == c

Android多线程任务的优化1:AsyncTask的缺陷 (转至 http://www.linuxidc.com/Linux/2011-09/43150.htm)

导语:在开发Android应用的过程中,我们需要时刻注意保障应用的稳定性和界面响应性,因为不稳定或者响应速度慢的应用将会给用户带来非常差的交互体验.在越来越讲究用户体验的大环境下,用户也许会因为应用的一次Force Close(简称FC)或者延迟严重的动画效果而卸载你的应用.由于现在的应用大多需要异步连接网络,本系列文章就以构建网络应用为例,从稳定性和响应性两个角度分析多线程网络任务的性能优化方法. 概述:为了不阻塞UI线程(亦称主线程),提高应用的响应性,我们经常会使用新开线程的方式,异步处理

Android ListView复杂列表优化实践

原文:Android ListView复杂列表优化实践 很多社交App都不免会涉及到复杂的列表元素实现,一个列表上面可能大量的图片,不定长的评论列表,给手机端的程序员带来了不少的挑战.本文就是在实现复杂的列表滑动的情况下,利用已知的优化方法指导下的一次优化实践,旨在提升ListView的滑动流畅度,为用户带来良好的体验. 1:设计稿: 这是列表中可能出现的ItemView,有两种,但是又有许多相同的地方,比如一样有点赞的图片,评论等...其中,评论和点赞的数量是可变的. 2:使用一般布局带来的问

Android之ListView/GridView 优化

一.效率最低的getView实现 我们知道,ListView和GridView的显示都是通过Adapter的getView实现的. ListView/GridView数据量较小时,我们的处理方式一般是这样的(效率最低的一种方式) 1 public View getView(int position, View convertView, ViewGroup parent) { 2 View item = mInflater.inflate(R.layout.list_item_icon_text,

ym——Android之ListView性能优化

Android之ListView性能优化 如果有看过我写过的15k面试题的朋友们一定知道,ListView的优化方式有以下几种: 重用了convertView ViewHolder static class ViewHolder 在列表里面有图片的情况下,监听滑动不加载图片 以上是大致的说了以下,应付面试已经足够了,如果要使用到项目中,可能有些初学者就迷茫了.接下来我详细的说一下,这个是如何优化的. 重用了convertView getView这个方法会调用的次数是你们的数据条目数*2,重用了c

蛋疼的Android BaseAdapter

1 package com.moniter.helperclasses; 2 3 import java.util.List; 4 5 import android.content.Context; 6 import android.view.LayoutInflater; 7 import android.view.View; 8 import android.view.ViewGroup; 9 import android.widget.BaseAdapter; 10 import andr

Android开发之SQLite优化

本文原地址为:http://blog.csdn.net/horkychen/article/details/18892223 关于SQLite的优化,首先是能用SQL语句批次处理的,就不要单笔操作,Cursor就更是能不用就不用.比如成批的DELETE/UPDATE,将条件组装到SQL语句,会比使用CURSOR一条条的查再删效率要高很多(若干年前就曾使用存储过程代替单笔操作,将一次批量计算时间从一天缩到了数分钟以内,参考).其次是对操作的优化:对于INSERT/UPDATE操作较多时使用事务,如