Android开发 | ListView 的使用与调优
本节我们将讲述如何使用ListView 的使用与调优,配合着视频 一起”下饭”,饭更香 !!
1. ListView 是什么?
2.ListView的基本使用
首先在XML布局界面中引入
ListView
1
2
3
4
5
6
7
8
9
10
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>定义
ListView
中item
的样式1
2
3
4
5
6
7
8
9
10
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"/>
</LinearLayout>将
ListView
中的item
定义为一个类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public class Bean {
private String name;
public Bean(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}准备数据 通过
List<Bean>
来存放数据1
2
3
4
5
6private List<Bean> data = new ArrayList<>();
for (int i = 0; i < 100; i++)
{
Bean bean = new Bean("LittleStone" + i);
data.add(bean);
}数据不能直接添加到
ListView
中,而是通过一个中间件Adapter
,所以我们还需要自定义个Myadapter
类(继承BaseAdapter
)来包裹数据, 最重要的函数getView
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39public class Myadapter extends BaseAdapter {
private List<Bean> data;
private Context context;
private String TAG = "Myadapter";
public Myadapter(Context context, List<Bean> data) {
this.context = context;
this.data = data;
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return data.get(position);
}
public long getItemId(int position) {
return position;
}
/**
* 每个item出现在屏幕中就会被调用
*/
public View getView(int position, View convertView, ViewGroup parent) {
convertView = LayoutInflater.from(context).inflate(R.layout.list_item, parent, false);
TextView textView = convertView.findViewById(R.id.tv);
textView.setText(data.get(position).getName());
Log.e(TAG, "getView: "+position );
return convertView;
}
}将
Adapter
与ListView
绑定,1
2ListView listView = findViewById(R.id.lv);
listView.setAdapter(new Myadapter(this, data));
3. ListView的调优过程
3.1使用convertView
来记录缓存
getview函数
形参中的convertView
记录了之前创建的convertView
,当第一次打开Android的ListView初始化时候,在Adapter中此时的convertView无疑均是空的,假设屏幕可以放m
条item,那么会创建m+1
个convertViewconvertView发生作用的地方,就是当ListView在向上/向下滑动过程中,convertView缓存和复用机制才发挥出来。比如当手指在屏幕自下往上翻动ListView时候,此时ListView头部的item将滚出设备屏幕,而底部的新item将加载出来,此时convertView的复用机制将发挥作用。由于此前在ListView初始化阶段已经创建了九个全新的convertView,Android系统将之前ListView初始化阶段创建的
m
个全新convertView都缓存起来,现在,由于ListView的上下翻动,顶部和底部之前显示的item滚出设备屏幕不可见,Android系统要么完全回收这些convertView,要么复用这些convertView。ListView的item有一个共同点:在大多数情况下,这些item的View( **指的是 布局是相同的 都是一个item xml文件)**是相同的,所以,明智的做法是继续复用,这样无疑会提高系统加载性能,要知道每一次创建新的convertView,是有一定系统开销的。1
2
3
4
5
6
7
8
9
10
11if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.list_item, parent, false);
Log.i(TAG, "位置" + position + ",创建convertView" + "index=" + index);
index += 1;
} else {
Log.i(TAG, "位置" + position + "使用缓存技术");
}
TextView textView = convertView.findViewById(R.id.tv);
textView.setText(data.get(position).getName());
// Log.e(TAG, "getView: " + position);
return convertView;打印的日志 除了一开始屏幕14+1个 创建convertView 其余的都会使用缓存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30com.littlestone.mylistview I/Myadapter: 位置0,创建convertViewindex=0
com.littlestone.mylistview I/Myadapter: 位置1,创建convertViewindex=1
com.littlestone.mylistview I/Myadapter: 位置2,创建convertViewindex=2
com.littlestone.mylistview I/Myadapter: 位置3,创建convertViewindex=3
com.littlestone.mylistview I/Myadapter: 位置4,创建convertViewindex=4
com.littlestone.mylistview I/Myadapter: 位置5,创建convertViewindex=5
com.littlestone.mylistview I/Myadapter: 位置6,创建convertViewindex=6
com.littlestone.mylistview I/Myadapter: 位置7,创建convertViewindex=7
com.littlestone.mylistview I/Myadapter: 位置8,创建convertViewindex=8
com.littlestone.mylistview I/Myadapter: 位置9,创建convertViewindex=9
com.littlestone.mylistview I/Myadapter: 位置10,创建convertViewindex=10
com.littlestone.mylistview I/Myadapter: 位置11,创建convertViewindex=11
com.littlestone.mylistview I/Myadapter: 位置12,创建convertViewindex=12
com.littlestone.mylistview I/Myadapter: 位置13,创建convertViewindex=13
com.littlestone.mylistview I/Myadapter: 位置14,创建convertViewindex=14
com.littlestone.mylistview I/Myadapter: 位置15,创建convertViewindex=15
com.littlestone.mylistview I/Myadapter: 位置0使用缓存技术
com.littlestone.mylistview I/Myadapter: 位置15使用缓存技术
com.littlestone.mylistview I/Myadapter: 位置16使用缓存技术
com.littlestone.mylistview I/Myadapter: 位置17使用缓存技术
.........
com.littlestone.mylistview I/Myadapter: 位置77使用缓存技术
com.littlestone.mylistview I/Myadapter: 位置93使用缓存技术
com.littlestone.mylistview I/Myadapter: 位置94使用缓存技术
com.littlestone.mylistview I/Myadapter: 位置95使用缓存技术
com.littlestone.mylistview I/Myadapter: 位置96使用缓存技术
com.littlestone.mylistview I/Myadapter: 位置97使用缓存技术
com.littlestone.mylistview I/Myadapter: 位置98使用缓存技术
com.littlestone.mylistview I/Myadapter: 位置99使用缓存技术
3.2 使用 自定义ViewHolder类来避免多次findViewByid
我们发现 findviewByid
会被多次调用,这也是非常耗时的,通过使用一个自定义的内部类Holder
里面放 item.xml的所需要控件 作为成员变量,在得到convertView
后调用 convertView
的setTag()
将Holder
作为形参放入
1 | Holder holder; |