当我们使用ListView时,必不可少的便会使用到adapter,adapter的用处就像是一个水管接口,把你想展现的数据与你希望展现的布局样式通过某种协定结合起来。
ArrayAdapter针对每个你想展示的列表项情况,你需要定义一个你的ArrayAdapter, 下面介绍一下如何定义一个你想要的水管接口:
对于每一项的展示内容,你需要设定一个对应的数据类,比如说你想展示一个城市列表,每项中有一个TextView和CheckBox,显示一个城市和它的选中情况,理论上你的数据类中就需要提供这些所想展示的数据,为了数据和视图对应得上,我们需要重写getView方法: "getView(int position, View convertView, ViewGroup parent)" 参数含义是:position:当前所绘制项在适配器中所处下标,你也可以理解为正在绘制第几个数据源的视图; convertView:当前传入的列表视图,可能为空,可能不为空(将当前不可见的视图复用);parent,父容器
1 if(convertView == null){ 2 convertView = getActivity().getLayoutInflater() 3 .inflate(R.layout.list_item_crime, null); 4 Log.i(TAG, "line 51"); 5 }
上面是一段很重要的代码,它的含义是仅当检查到传入的绘制视图为空时,才会先建一个视图加入列表中;重用视图的意义在于尽量减少对视图的不必要消耗,想象有超过100项的列表,你的屏幕上只能显示其中的10项,那你就需要一直维护暂时不需要用到的90项的视图,1%的利用率,所以我们需要重用视图,当视图往下滑时,当有项消失不见时,这时的视图就会被传入到新项绘制的getView函数中作为参数:convertView,再去复写:假设我的数据源是一个CityItem,有两个值一个是城市名称,一个是该城市是否处于选中状态;这时为了能展示出来,我的布局选项 “R.layout.list_item_crime” 就需要对应有一个TextView 和 CheckBox,通过findViewById找到对应组件后赋值:
1 @Override 2 public View getView(final int position, View convertView, ViewGroup parent) { 3 if (convertView == null) { 4 convertView = getLayoutInflater().inflate( 5 R.layout.city_list_item, null);//希望展示出来的布局样式,内含有一个textview和checkbox,id分别是R.id.city_name和R,id.isSelected 6 } 7 CityItem c = cityItems.get(position); 8 TextView titleView = (TextView) convertView 9 .findViewById(R.id.city_name);//通过Id找到组件 10 titleView.setText(c.getName());//赋值 11 12 CheckBox selectedCheckBox = (CheckBox) convertView 13 .findViewById(R.id.isSelected); 14 15 selectedCheckBox.setChecked(c.getSelected()); 16 return convertView; 17 }
之后你也可以自定义一个构造方法,
1 public CityAdapter(ArrayList<CityItem> crimes,Context context) { 2 super(context, 0, crimes); 3 }
这样我建立一个适配器时只用传入我关心的数据源和上下文,这样一个自定义的ArrayAdapter就写好了;
怎么用呢?找到对应的ListView视图,加入适配器即可,
1 cityAdapter = new CityAdapter(cityItems, this); 2 cityList.setAdapter(cityAdapter);