第一次写博客,希望大家喜欢
先来简单的创建撒~然后再慢慢优化,发出来供大家交流经验,嘿嘿
先说说listview的原理撒
其实listview 可以看做一个框架子,他有一个整体的框框,还有一个一个的行,
就像这样(图是我自己画的。。。不知道这样理解够不够完善,但是写代码的时候就是这个思路了)
1、首先创建项目咯~
2、在activity_main.xml中拖入ListView的组件(组件在composite中)
刚加进去的代码是这样的
1
2
3
4
5
6
7
|
<ListView
android:id=
"@+id/listView1"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_alignParentLeft=
"true"
android:layout_alignParentTop=
"true"
>
</ListView>
|
一定要注意将layout_height的值改为match_parent,否则在运行时会出现跳行的情况(具体原因是:在activity加载ListView的时候,如果ListView的高度为适应内容,那么每次加载行的时候都会重新运算一遍,所以如果打日志的话 会发现 原本只有6行的显示,却打了好多行日志)
3、在layout里面新建个行布局(布局就随便了,我一般用RelativeLayout,如果是只需要一个文本的话,只用一个TextView 也是可以的)
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<?xml version=
"1.0"
encoding=
"utf-8"
?>
<RelativeLayout xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
>
<TextView
android:id=
"@+id/textView1"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_alignParentLeft=
"true"
android:layout_alignParentTop=
"true"
android:text=
"Large Text"
android:textAppearance=
"?android:attr/textAppearanceLarge"
/>
</RelativeLayout>
|
也可以直接这样的
1
2
3
4
5
6
7
8
9
|
<TextView
android:id=
"@+id/textView1"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_alignParentLeft=
"true"
android:layout_alignParentTop=
"true"
android:text=
"Large Text"
android:textAppearance=
"?android:attr/textAppearanceLarge"
>
</TextView>
|
ok UI(布局文件) 这样就可以了 简单的来么
现在来看代码
在MainActivity.java中的onCreate方法中加入先读取layout中的listview
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
|
@Override
protected
void
onCreate(Bundle savedInstanceState)
{
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView) findViewById(R.id.listView1);
//读取listView的
BaseAdapter adapter =
new
BaseAdapter()
//创建一个适配器,这是一个内部类了
{
@Override
public
View getView(
int
position, View convertView, ViewGroup parent)
{
/*
* getView 加载每一行的时候系统会自动调用这个方法,所以要在这个方法中创建当前行样式
* 主要参数:1、position:当前行的id
* 2、convertView:当listview滑动式缓存消失的行布局
* 3、parent:The parent that this view will eventually be attached to
* (额这是官方解释了。。。sorry~ 没用过具体怎么样我也不太清楚)
*/
//开始创建行,
LayoutInflater inflater = getLayoutInflater();
RelativeLayout layout = (RelativeLayout) inflater.inflate(R.layout.list_item,
null
);
//以上两行代码 获取每行的布局
//有了layout就可以获取当前行的组件了,组件拿到了,也就可以设置该组件的值了
TextView textView = (TextView) layout.findViewById(R.id.textView1);
textView.setText(
"title"
+position);
//前面有说过position是代表当前行的id 从零开始计数
return
layout;
//一定要记得将创建好的行布局 返回给 系统,不然 你讲神马都看不到了
}
@Override
public
long getItemId(
int
position)
//这个方法还有getItem()方法 我都没有用过,具体什么效果 //大家可以试试撒
{
return
0
;
}
@Override
public
Object
getItem(
int
position)
{
return
null
;
}
@Override
public
int
getCount()
//设置要创建多少行
{
return
10
;
//表示要创建10行
}
};
listView.setAdapter(adapter);
//将创建的适配器(adapter)放到listview中
}
|
这样就ok了 一个简单的listview 就搞好了,可以在模拟器上运行下试试撒~
但是这样的代码还是有很多问题的,你可以在getView中打印下日志,输出创建的layout,你就会发现竟然每一行的layout都是新的,这样的话很消耗系统资源,(10行可能太少了,多搞点,在拖动的时候 就会发现了,写多少行,就给你高多少个layout)
所以android官方 推荐用convertView+ViewHolder的方式来提高性能,这样系统只会创建当前页显示数量+1个layout,就可以是layout复用,其他的行都只用创建好的layout就可以了
优化代码如下:
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
|
class
ViewHolder{
//ViewHolder自己创建就好了,这是内部类,因为当前类只要MainActivity使用就好了,所以不需要新建一个class文件了
TextView mTextView;
//官方的源代码中,成员变量就是这样写的
//(前面加个m这样只要看到他就知道这个变量是成员变量了,后面名字随便)
}
@Override
protected
void
onCreate(Bundle savedInstanceState)
{
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView) findViewById(R.id.listView1);
//读取listView的
BaseAdapter adapter =
new
BaseAdapter()
//创建一个适配器,这是一个内部类了
{
@Override
public
View getView(
int
position, View convertView, ViewGroup parent)
{
/*
* getView 加载每一行的时候系统会自动调用这个方法,所以要在这个方法中创建当前行样式
* 主要参数:1、position:当前行的id
* 2、convertView:是一个缓存,存取listview滑动时缓存最先消失的那个行布局,
* 后面显示的行就可以复用这个convertView了,这样就可以达到复用的效果,节省资源
*
* 3、parent:The parent that this view will eventually be attached to
* (额这是官方解释了。。。sorry~ 没用过具体怎么样我也不知道)
*/
//开始创建行,
RelativeLayout layout =
null
;
ViewHolder holder =
null
;
if
(convertView ==
null
){
//当缓存为空是 创建layout
LayoutInflater inflater = getLayoutInflater();
layout = (RelativeLayout) inflater.inflate(R.layout.list_item,
null
);
//以上两行代码 获取每行的布局
holder =
new
ViewHolder();
//创建holder;
holder.mTextView = (TextView) layout.findViewById(R.id.textView1);
//讲获取到的行组件放入holder中
/*这里存在一个问题 layout是两个东西怎样将 layout和holder联系在一起呢?
*不用担心,View类提供了一个方法,setTag(Object obj);
*这个方法可以将holder像一个物品一样放入一个叫Tag 的袋子里
*这样就可以 复用 行布局和布局中的组件了
**/
layout.setTag(holder);
}
else
{
//有缓存时 就直接将缓存中的convertView给layout就好了
layout = (RelativeLayout) convertView;
holder = (ViewHolder) layout.getTag();
}
//更新组件内容
holder.mTextView.setText(
"title"
+position);
//前面有说过position是代表当前行的id 从零开始计数
return
layout;
//一定要记得将创建好的行布局 返回给 系统,不然 你讲神马都看不到了
}
@Override
public
long getItemId(
int
position)
{
return
0
;
}
@Override
public
Object
getItem(
int
position)
{
return
null
;
}
@Override
public
int
getCount()
//设置要创建多少行
{
return
10
;
//表示要创建10行
}
};
listView.setAdapter(adapter);
//将创建的适配器(adapter)放到listview中
}
|
呵呵 优化好啦,这时候可以试试在打日志看看,