要给listView设置列表数据需要掌握adapter的使用,这也是最基本的用法,初次之外的好多面试中曾被问到这样的问题:你可以说说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;
}
- 如果你要加载多种布局那么首先你一定重写这两个方法
- getItemViewType(int position) 获取某个position位置的布局格式
@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写的购物车例子,之后与大家分享。
不只是一个单纯的列表(里面有点击选中的按钮,所以一般的复用模式得适当改变),如下图就是实现的效果:
上图,我们实现的效果就是实现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;
}
选中状态错乱的问题
* 首先导致选中错乱的原因
在getView方法中做了布局的复用,导致除了布局复用之外,选中的状态也复用了,这样,解决这个问题的方式有好几种吧,不过我只讲一种,因为我只会一种,好吧,我们继续,首先,我们要给每个item设置一个状态:
private List 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 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的点击事件的一些问题吧,实际开发中遇到