转载请标明出处:http://blog.csdn.net/qq1940879801/article/details/50240223
前一篇介绍listview原理,这篇接着讲listview优化
优化一:复用convertView
Listview自身考虑了优化的问题,在复写的Adapter类中,主要复写getCount()和getView()。界面上有多少条item显示,就会调用多少次的getView()方法。因此如果在每次调用的时候,如果不进行优化,每次都会使用LayoutInflate.from(context).infate(..),将xml文件解析,并显示在界面上,这是非常消耗资源的。因为有新的内容产生就需要产生新的view来存放并销毁旧的view,所以,可以复用旧的view用来存放新的内容。
优化二:缓存item条目的引用-----ViewHolder
findViewById()这个方法是比较耗性能的操作。
findViewById()原理:从最顶端的节点进行一层一层的解析,找到后再一层一层的返回,如果在左边没找到,就会接着解析右边,并进行相应的查询,直到找到位置。因此可以对findViewById进行优化处理。xml文件被解析的时候,只要被创建出来了,其孩子的id就不会改变。根据这个特点,可以将孩子id存入到指定的集合中,每次就可以直接取出集合中对应的元素就可以了。
优化三:listview中数据的分批及分页加载
假如listview有几十万条数据要显示,如果将几十万条数据直接加载到内存,是很消耗内存,怎么办?
先获取一些数据显示在界面上,以后每次只获取一些数据并显示在界面,实现分页显示
优化四:滑动的时候不加载数据,滑动停止才开始加载数据。
使用map存储之前使用过的数据,对数据进行复用并防止item错位
在src/包名新建
FruitAdapter类
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
import
java.util.HashMap;
import
java.util.List;
import
android.content.Context;
import
android.util.Log;
import
android.view.LayoutInflater;
import
android.view.View;
import
android.view.ViewGroup;
import
android.widget.ArrayAdapter;
import
android.widget.TextView;
import
com.example.listviewtext.R;
import
com.example.listviewtext.bean.Fruit;
/**
* @ClassName: FruitAdapter
* @Description: TODO
* @Author: Jesse
* @Date: 2015-12-9 下午8:51:26
* @Copyright: 2015 Jesse Inc. All rights reserved.
*/
public
class
FruitAdapter
extends
ArrayAdapter<Fruit> {
private
Context mContext;
private
int
resourseId;
/** 判断是否是初始化 */
public
boolean
isInit =
false
;
/** 缓存数据 */
public
HashMap<Integer, String> map =
new
HashMap<Integer, String>();
public
FruitAdapter(Context context,
int
resource, List<Fruit> objects) {
super
(context, resource, objects);
mContext = context;
resourseId = resource;
}
@Override
public
View getView(
int
position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if
(convertView ==
null
) {
convertView = LayoutInflater.from(mContext).inflate(resourseId,
null
);
viewHolder =
new
ViewHolder();
viewHolder.tv_url = (TextView) convertView
.findViewById(R.id.tv_url);
viewHolder.tv_name = (TextView) convertView
.findViewById(R.id.tv_name);
convertView.setTag(viewHolder);
}
else
{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.tv_url.setTag(position);
// 设置tag标签,配合map进行复用并解决错位
Fruit fruit = getItem(position);
viewHolder.tv_name.setText(fruit.getName());
/** 加载图片默认没滑动 */
if
(!isInit) {
map.put(position, fruit.getIndex());
viewHolder.tv_url.setText(fruit.getIndex());
Log.d(
"adapter"
,
"fruit.getIndex()="
+ fruit.getIndex());
}
Log.e(
"TAG"
,
"position="
+ position);
return
convertView;
}
class
ViewHolder {
TextView tv_url;
TextView tv_name;
}
}
|
FirstActivity类
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
import
java.util.ArrayList;
import
java.util.List;
import
android.os.Bundle;
import
android.util.Log;
import
android.widget.AbsListView;
import
android.widget.AbsListView.OnScrollListener;
import
android.widget.ListView;
import
android.widget.TextView;
import
com.example.listviewtext.R;
import
com.example.listviewtext.adapter.FruitAdapter;
import
com.example.listviewtext.bean.Fruit;
import
com.jesse.base.BaseActivity;
/**
* @ClassName: FirstActivity
* @Description: TODO
* @Author: Jesse
* @Date: 2015-12-6 下午4:23:08
* @Copyright: 2015 Jesse Inc. All rights reserved.
*/
public
class
FirstActivity
extends
BaseActivity
implements
OnScrollListener {
/** 初始化存储数据 */
private
List<Fruit> fruits;
/** 列表显示第一个可见对应item的位置,列表显示最后一个可见对应item的位置 */
private
int
start_index, end_index;
private
FruitAdapter fruitAdapter;
private
ListView lv_fruit;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
}
@Override
protected
int
initLayout() {
return
R.layout.aty_main;
}
@Override
protected
void
initData() {
fruits =
new
ArrayList<Fruit>();
for
(
int
i =
0
; i <
40
; i++) {
fruits.add(
new
Fruit(
"www.jesse.com\\"
+ i,
"qq"
+ i));
}
}
@Override
protected
void
initView() {
lv_fruit = (ListView) findViewById(R.id.lv_fruit);
fruitAdapter =
new
FruitAdapter(
this
, R.layout.item_fruit, fruits);
lv_fruit.setAdapter(fruitAdapter);
}
@Override
protected
void
addListen() {
lv_fruit.setOnScrollListener(
this
);
}
/**
* 滑动状态改变的时候调用 scrollState值: 当屏幕停止滚动时为SCROLL_STATE_IDLE = 0;
* 当屏幕滚动且用户使用的触碰或手指还在屏幕上时为SCROLL_STATE_TOUCH_SCROLL = 1;
* 由于用户的操作,屏幕产生惯性滑动时为SCROLL_STATE_FLING = 2
*/
@Override
public
void
onScrollStateChanged(AbsListView view,
int
scrollState) {
Log.e(
"TAG"
,
"scrollState="
+ scrollState);
fruitAdapter.isInit =
true
;
switch
(scrollState) {
case
OnScrollListener.SCROLL_STATE_IDLE:
// listview滑动停止
for
(; start_index < end_index; start_index++) {
/** 通过tag标签获取 */
TextView tv_url = (TextView) lv_fruit
.findViewWithTag(start_index);
/** 通过缓存获取数据 */
String str = fruitAdapter.map.get(start_index);
if
(str !=
null
) {
tv_url.setText(str);
Log.d(
"First"
,
"str="
+ str);
}
else
{
fruitAdapter.map.put(start_index, fruits.get(start_index)
.getIndex());
tv_url.setText("");
tv_url.setText(
""
+ fruits.get(start_index).getIndex());
Log.d(
"First"
,
"start_index="
+ start_index);
}
}
break
;
}
}
@Override
public
void
onScroll(AbsListView view,
int
firstVisibleItem,
int
visibleItemCount,
int
totalItemCount) {
Log.e(
"TAG"
,
"firstVisibleItem="
+ firstVisibleItem
+
"\n,visibleItemCount="
+ visibleItemCount
+
"\n,totalItemCount="
+ totalItemCount);
/** 设置当前屏幕显示的起始index和结束index */
start_index = firstVisibleItem;
end_index = firstVisibleItem + visibleItemCount;
/** listview最后一个item */
if
(end_index >= totalItemCount) {
end_index = totalItemCount;
}
}
}
|