Android BaseAdapter和ViewHolder 最佳化 解決ListView的item搶焦點問題和item錯亂問題

來源:互聯網
上載者:User

標籤:listen   ted   esc   應該   resid   view   nal   資料   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 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));        }    }

關於SparseArray

 SparseArray 內部實現是Array數組。當長度不夠時,會調用System.arrayCopy
        內部有 keys和values兩個數組。


        put(key, value); 二分法尋找key應該存放的位置  由於key是Integer類型
        put、get時 兩個數組都是操作的同一個位置上的資料


    SparseArray 用於替代形如  HashMap<Integer, Object>
    SparseBooleanArray 用於替代形如  HashMap<Integer, Boolean>
    SparseIntArray 用於替代形如  HashMap<Integer, Integer>
    SparseLongArray 用於替代形如  HashMap<Integer, Long>

  support.v4.util.SparseArrayCompat 提供了v4包相應平台的 SparseArray實現


Android BaseAdapter和ViewHolder 最佳化 解決ListView的item搶焦點問題和item錯亂問題

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.