欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 运维知识 > Android >内容正文

Android

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

发布时间:2025/4/14 Android 63 豆豆
生活随笔 收集整理的这篇文章主要介绍了 Android BaseAdapter和ViewHolder 优化 解决ListView的item抢焦点问题和item错乱问题 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

首先赞下hyman大神

曾经仅仅是简单的重写个BaseAdapter,将getView方法保持抽象。而ViewHolder没有抽象过。

。。


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

/*** author : stone* email : aa86799@163.com* time : 15/7/24 14 27*/ public class StoneViewHolder {private int mPosition;private View mConvertView;private SparseArray<View> mViews; //管理listView-item中的viewpublic 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, ViewconvertView, ViewGroup parent) {if (convertView == null) {return new StoneViewHolder(context, layoutId, position, parent);} else {StoneViewHolder holder = (StoneViewHolder) convertView.getTag();holder.mPosition = position; //更新复用的convertView中 positionreturn 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 : aa86799@163.com* 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;}@Overridepublic int getCount() {return mData.size();}@Overridepublic T getItem(int position) {return mData.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic 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) {@Overrideprotected 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() {@Overridepublic 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);}@Overrideprotected void getView(Context context, final StoneViewHolder holder, final int position) {CheckBox cb = holder.getView(R.id.cb_check);cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {@Overridepublic 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实现


转载于:https://www.cnblogs.com/yfceshi/p/6786035.html

总结

以上是生活随笔为你收集整理的Android BaseAdapter和ViewHolder 优化 解决ListView的item抢焦点问题和item错乱问题的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。