【Android】使用自定义Adapter优化ListView、修改数据及控件内部布局

之前使用 SimpleAdapter去显示ListView,当item很多时,系统会对每一条进行创建,但显示的却每次只有几条,有很多无用的item占据了内存,使用继承于BaseAdapter的adapter,通过重写各种方法,可以很好的帮助我们进行List显示,同时,BaseAdapter也支持GridView和Spinner,可对其他内容起到作用。
同样,对于数据存储存储在private ArrayList> list;
MainActivity中的配置adapter和设置listView点击事件(这里不推荐使用这种方式,尽量将所有item事件响应放在adapter中)比较简单

MyAdapter adapter=new MyAdapter(this);
        listView.setAdapter(adapter);
         listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView parent, View view, int position, long id) {
                *************       
                 });

之后看最主要的Myadapter类

  private class MyAdapter extends BaseAdapter {
        private LayoutInflater inflater;//LayoutInfalter对象用来导入布局

        public MyAdapter(Context context) {
            this.inflater = LayoutInflater.from(context);
        }

        @Override
        public int getCount() {         //返回list项目的个数,在实际中,一般都是数据库中得到的数据条数
            return (list.size());
        }

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

        }

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

        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView==null) {            //判断convertView是否为null 一般在最初绘制ListView的时候都为null
                                                //随着绘制占据完屏幕 之后再将ListView移动 convertView的值将不为null
                                                //而是之前被绘制过的值
                convertView =inflater.inflate(R.layout.list_items_layout,null); //list_items_layout为自定义的布局
                holder=new ViewHolder();
                holder.item_bt_delete=(Button)convertView.findViewById(R.id.list_items_bt_delete);
                holder.item_tv_date=(TextView)convertView.findViewById(R.id.list_items_date);
                holder.item_tv_detail=(TextView)convertView.findViewById(R.id.list_items_detail);
                holder.item_tv_dbnumber=(TextView)convertView.findViewById(R.id.list_items_dbnumber);
                holder.item_tv_number=(TextView)convertView.findViewById(R.id.list_items_number);
                convertView.setTag(holder);     //绑定holder
            }else{
                holder=(ViewHolder)convertView.getTag(); //若convertView不为null 则说明之前对其绑定过 只需要重新拿出来即可
            }

            //配置数据
            holder.item_tv_detail.setText(list.get(position).get("detail").toString());
            holder.item_tv_date.setText(list.get(position).get("date").toString());
            holder.item_tv_dbnumber.setText(list.get(position).get("dbnumber").toString());

            holder.item_bt_delete.setOnClickListener(new View.OnClickListener() {  //添加item中按钮的响应事件
                @Override
                public void onClick(View v) {
                    int key=Integer.parseInt(list.get(position).get("dbnumber").toString());
                    mgr.delete(key);
                    display();
                }
            });
            return convertView;

        }

         public final class ViewHolder{
              public Button item_bt_delete;
              public TextView item_tv_detail;
              public TextView item_tv_date;
              public TextView item_tv_dbnumber;
              public TextView item_tv_number;
         }

    }

具体内容看代码中的注释
listView在开始绘制的时候,首先调用getCount()函数,根据他的返回值得到listView的长度之后调用getView()逐一绘制每一行。

convertView的动态重用机制,将屏幕外的convertView回收并重新分发给进入屏幕的item,始终保证只有屏幕能够容下的item数量进行分配。

使用ViewHolder来方便我们对于adapter中控件的管理,其中在获取其android.R.id值得时候,注意使用convertView.finViewById()

convertView的setTag()和getTag()可以看做是数据与convertView对象的绑定和获取,跟随绑定的数据一起变化。


注:若想根据外围事件改变item控件的内容或者属性(例如长按listview改变控件Visibility),由于convertView代表了ListView的一个选项,是一个View对象,我们直接用convertView.setOnLongClickListener()设置convertView的事件即可,还有尽可能的将所有对item的操作都放在adapter当中,方便代码的调用


Button控件会抢夺listView的焦点,注意在xml中修改其值为false
android:focusable="false"

你可能感兴趣的:(android,ListView)