待修改-精通安卓Android知识Android开发

listVeiw之adapter使用优化及item选中状态的处理

2017-03-06  本文已影响285人  549f95307939

要给listView设置列表数据需要掌握adapter的使用,这也是最基本的用法,初次之外的好多面试中曾被问到这样的问题:你可以说说listView的优化吗?相信不少被问到,今天我们就来解决下这个问题;好了直接上代码:

继承BaseAdapter来使用ListView

以下是继承之后需要实现的方法,我们来具体看看每个方法的作用

@Override
    public int getCount() {
        return mData.size();
    }
@Override
    public Object 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) {
        Log.d(TAG, "显示:" + position + "行,调用getView()" + "参数convertView==null?" + (convertView == null));
        View rootView = null;
        //如果没有可以重用的控件
        if (convertView == null) {
            LayoutInflater inflater = LayoutInflater.from(mContext);
            rootView = inflater.inflate(R.layout.my_list_item, parent, false); //加载布局,创建View
            rootView.setTag(position);
            Log.d(TAG, "实例化rootView,保存到Tag中的值为:" + position);
            counter++;
            Log.d(TAG, "控件实例化个数:" + counter);
        } else {
            //控件己经被创建过,直接重用
            rootView = convertView;
        }
        //依据位置提取相应的数据源对象
        MyDataClass item = mData.get(position);
        //获取用于显示内容的控件的引用
        TextView titleTextView = (TextView) rootView.findViewById(R.id.tvTitle);
        TextView detailTextView = (TextView) rootView.findViewById(R.id.tvDetail);
        //设置显示内容
        titleTextView.setText(item.getTitle());
        detailTextView.setText(item.getDetail() + " 本行Tag中保存的值为:" + rootView.getTag());
        return rootView;
    }
如果你要加载多种布局那么首先你一定重写这两个方法

@Override
public int getItemViewType(int position) {
    if(position==2){
    return 2;
    }
    return 1;
    //根据具体情况来判断
}
@Override
public int getViewTypeCount() {
    return 2;
}

本文看到这里,感觉没有重点,如果是这样,那么这篇文章就等于白写了,实际运用中,我们最关键的就是用到getView()的优化来使得listView的item能够重复利用资源,从而大大的加快了加载的速度,体验更好,当然实际运用中可能你会遇到以下的难点,以下都是实际项目中血淋林的教训,在此罗列出来,下篇有专门写的demo分析这些问题

1.当listView的item中有选中状态效果,比如用到最多的地方,像购物车的例子这样,有选中的判断,如果状态复用的话选中就会错乱,针对这样的问题该怎么解决;
2.再次讲讲不同布局在listview中是怎么使用的;
3.当每个item需要添加实时刷新的数据的时候,设置点击的时候会失去状态,这是为甚么,该怎么解决;
4.以上几个都有分开写的demo,最后还有一个综合的listView写的购物车例子,之后与大家分享。

接下来我们就开始在实战中学习战争

1.分析需求

不只是一个单纯的列表(里面有点击选中的按钮,所以一般的复用模式得适当改变),如下图就是实现的效果:

效果图

上图,我们实现的效果就是实现listview中的两种不同布局的填充,其次就是当列表中有选中状态的时候如何避免滑动时的状态复用,针对这两个问题,我们来看代码:

 @Override
    public int getItemViewType(int position) {
        if (getItemId(position) == 3 || getItemId(position) == 10) {
            return 1;
        }
        return 0;
    }

    @Override
    public int getViewTypeCount() {
        return 2;
    }
@Override
    public View getView(final int i, View view, ViewGroup viewGroup) {
        final ViewHolder viewHolder;
        if (view == null) {
            viewHolder = new ViewHolder();
            if (getItemViewType(i) == 0)  {
                view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.iten_view, null);
            } else {
                view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_teo, null);
            }
            viewHolder.cbbox = (CheckBox) view.findViewById(R.id.cb_my);
            viewHolder.tvMy = (TextView) view.findViewById(R.id.tv_coments);
            view.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) view.getTag();
        }
        
        return view;
        private class ViewHolder {
        public CheckBox cbbox;
        public TextView tvMy;
    }

选中状态错乱的问题

    private List<Boolean> booleenList;
    //声明一个boolean类型的集合
    
    ~~~
    
    //初始化数据
    private void initData() {
        lvtext = (ListView) this.findViewById(R.id.lv_lv);
        myAdapter = new MyAdapter();
        stringList = new ArrayList<>();
        booleenList = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            stringList.add("im is" + i + "name");
            booleenList.add(false);
            //初始化数据的时候每个数据加个false的状态
        }
    }
    
    ~~~
    
    myAdapter.setData(stringList);
    myAdapter.setBoolData(booleenList);
    //这个步骤很明显就是传值

接下来看我在adapter中是怎么处理的

  @Override
    public View getView(final int i, View view, ViewGroup viewGroup) {
        final ViewHolder viewHolder;
        if (view == null) {
            viewHolder = new ViewHolder();
            if (getItemViewType(i) == 0) {
                view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.iten_view, null);
            } else {
                view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_teo, null);
            }
            viewHolder.cbbox = (CheckBox) view.findViewById(R.id.cb_my);
            viewHolder.tvMy = (TextView) view.findViewById(R.id.tv_coments);
            view.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) view.getTag();
        }
        viewHolder.tvMy.setText(data.get(i));
        //注意以下这行代码
        viewHolder.cbbox.setChecked(boolData.get(i));
        viewHolder.cbbox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //这里直接调用方法
                //MainActivity.selectChange(i, boolData);
                //自定义的接口
                slecct.seleckt(i, boolData);
            }
        });
        return view;
    }

//可以直接使用
    public static void selectChange(int i, List<Boolean> boolData) {
        if (boolData.get(i) == true) {
            boolData.set(i, false);
            myAdapter.notifyDataSetChanged();
        } else if (boolData.get(i) == false) {
            boolData.set(i, true);
            myAdapter.notifyDataSetChanged();
        }
    }

以上的代码,暂且到这里好了,这些代码比较简单,我自己有写具体的demo,但是没有上传到github,因为这代码量确实少,还希望自己看着贴出的代码了解了解吧!,下一篇的时候,我们继续讲讲listview的item的点击事件的一些问题吧,实际开发中遇到
有兴趣的可以继续学习下一篇:listView之item点击失效,长按消失了的问题

想交流,学习,提意见的可以关注以下的二维码:

公众号:君不见And
上一篇下一篇

猜你喜欢

热点阅读