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 }