Android中ListView控件的使用
ListView展示数据的原理
在Android中,其实ListView就相当于web中的jsp,Adapter是适配器,它就相当于web中的Servlet,
适配器的作用
Adapter的作用就是把数据展示在Listview中
使用ListView的奇怪问题?
在使用ListView的时候,如果把ListView的高设置为wrap_content,它会反复读取多次数据,然后在ListView中把数据显示出来,效率非常低,,这时候我们应该把ListView的高设置为match_parent,这样就能很好的解决读取多次再显示数据的问题了,因为ListView的高写成wrap_content,那么它的高不确定的,需要做多次的校验,确认数据是否能完全显示出来。
下面我们通过案例说明这个问题
当ListViewf控件的高度设置为wrap_content时,就会出现以下问题,如下图:
图1 图2
我们可以看到手机屏幕图1中最多能够显示31条数据,但是图2中很明显看到当加载完31条记录时,紧接着又从0开始加载这31条记录,其实后面还加载了好几次,在这里就不一一截图出来了,那么如何解决呢?其实只需要修改一下ListView控件的高就可以了,把ListView控件中的高设置为match_parent
但是还要注意一点,当是引入布局的时候,我们也需要设置它的父元素的高为match_parent
也就是说,父元素和引入布局的ListView都需要设置为match_parent
ListView控件的父子关系关系也是一样
解决了读取多次数据问题后,我们来看看以下代码,然后运行看看结果是怎样的?
1 import android.app.Activity;
2 import android.os.Bundle;
3 import android.view.View;
4 import android.view.ViewGroup;
5 import android.widget.BaseAdapter;
6 import android.widget.ListView;
7 import android.widget.TextView;
8
9
10 public class MainActivity extends Activity {
11
12 @Override
13 protected void onCreate(Bundle savedInstanceState) {
14 super.onCreate(savedInstanceState);
15 setContentView(R.layout.weixin);
16
17 //获取所需控件
18 ListView ll = (ListView) findViewById(R.id.listView1);
19
20 //使用适配器
21 ll.setAdapter(new MyAdapter());
22
23 }
24
25 //定义一个适配器
26 private class MyAdapter extends BaseAdapter{
27
28 //返回条目数
29 @Override
30 public int getCount() {
31 return 10000;
32 }
33
34 @Override
35 public Object getItem(int position) {
36
37 return null;
38 }
39
40 @Override
41 public long getItemId(int position) {
42
43 return 0;
44 }
45
46 /**
47 * 获取一个view,用来显示listView的数据,会作为listView的一个条目显示
48 *
49 * position : 对应getCount()返回的索引
50 * convertView : 缓存数据的对象
51 */
52 @Override
53 public View getView(int position, View convertView, ViewGroup parent) {
54
55 /**
56 * 如果convertView是null,那么说明没有缓存,那么我们就创建TextView对象
57 */
58 TextView tv = tv = new TextView(MainActivity.this);
59 System.out.println("创建新的View"+position);
60
62 tv.setText("呵呵"+position);
63 return tv;
64 }
65
66 }
67 }
运行结果:
我们从结果可以看到,每次都是创建了一个新的对象,这样效率非常低,那么我们下面进行ListView的优化
ListView的优化策略
1 package com.example.uicustomviews;
2
3 import android.app.Activity;
4 import android.os.Bundle;
5 import android.view.View;
6 import android.view.ViewGroup;
7 import android.widget.BaseAdapter;
8 import android.widget.ListView;
9 import android.widget.TextView;
10
11
12 public class MainActivity extends Activity {
13
14 @Override
15 protected void onCreate(Bundle savedInstanceState) {
16 super.onCreate(savedInstanceState);
17 setContentView(R.layout.weixin);
18
19 //获取所需控件
20 ListView ll = (ListView) findViewById(R.id.listView1);
21
22 //使用适配器
23 ll.setAdapter(new MyAdapter());
24
25 }
26
27 //定义一个适配器
28 private class MyAdapter extends BaseAdapter{
29
30 //返回条目数
31 @Override
32 public int getCount() {
33 return 10000;
34 }
35
36 @Override
37 public Object getItem(int position) {
38
39 return null;
40 }
41
42 @Override
43 public long getItemId(int position) {
44
45 return 0;
46 }
47
48 /**
49 * 获取一个view,用来显示listView的数据,会作为listView的一个条目显示
50 *
51 * position : 对应getCount()返回的索引
52 * convertView : 缓存数据的对象
53 */
54 @Override
55 public View getView(int position, View convertView, ViewGroup parent) {
56
57 TextView tv = null;
58
59 /**
60 * 如果convertView是null,那么说明没有缓存,那么我们就创建TextView对象
61 */
62 if(convertView==null){
63 System.out.println("创建新的View"+position);
64 tv = new TextView(MainActivity.this);
65 }else{
66 /**
67 * 否则就是有缓存,为了提高效率,那么我们就使用缓存中对象,不需要再次new了
68 */
69 tv = (TextView) convertView ;
70 System.out.println("使用缓存的View"+position);
71 }
72
73 tv.setText("呵呵"+position);
74 return tv;
75 }
76
77 }
78 }
运行结果如下图:
显然提高了效率,不再创建新的View,而是使用了缓存中的View
下面我们把一个布局文件转为一个View(ListView中的一个条目)
1 package com.example.uicustomviews;
2
3 import android.app.Activity;
4 import android.os.Bundle;
5 import android.view.LayoutInflater;
6 import android.view.View;
7 import android.view.ViewGroup;
8 import android.widget.BaseAdapter;
9 import android.widget.ListView;
10
11
12
13 public class MainActivity extends Activity {
14
15 @Override
16 protected void onCreate(Bundle savedInstanceState) {
17 super.onCreate(savedInstanceState);
18 setContentView(R.layout.weixin);
19
20 //获取所需控件
21 ListView ll = (ListView) findViewById(R.id.listView1);
22
23 //使用适配器
24 ll.setAdapter(new MyAdapter());
25
26 }
27
28 //定义一个适配器
29 private class MyAdapter extends BaseAdapter{
30
31 //返回条目数
32 @Override
33 public int getCount() {
34 return 10000;
35 }
36
37 @Override
38 public Object getItem(int position) {
39
40 return null;
41 }
42
43 @Override
44 public long getItemId(int position) {
45
46 return 0;
47 }
48
49 /**
50 * 获取一个view,用来显示listView的数据,会作为listView的一个条目显示
51 *
52 * position : 对应getCount()返回的索引
53 * convertView : 缓存数据的对象
54 */
55 @Override
56 public View getView(int position, View convertView, ViewGroup parent) {
57
58 /**
59 * 可以插入广告
60 */
61
62 View view = null;
63
64 /**
65 * 如果convertView是null,那么说明没有缓存,那么我们就创建TextView对象
66 */
67 if(convertView==null){
68 //System.out.println("创建新的View"+position);
69 //创建一个新的View对象,可以通过打气筒把一个布局资源转换成一个View对象
70 //resource就是我们定义好的布局文件
71 //方式一
72 //view = View.inflate(MainActivity.this, R.layout.weixin_item, null);
73
74 //方式二
75 //view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.weixin_item, null);
76
77 //方式三
78 LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
79
80 view = inflater.inflate(R.layout.weixin_item, null);
81 }else{
82 /**
83 * 否则就是有缓存,为了提高效率,那么我们就使用缓存中对象,不需要再次new了
84 */
85 view = convertView ;
86 //System.out.println("使用缓存的View"+position);
87 }
88
90 return view;
91 }
92
93 }
94 }