Android之listview && adapter

  今天我们讲的也是非常重要的一个控件listview—最常用也是最难的

一个ListView通常有两个职责

(1)将数据填充到布局。

(2)处理用户的选择点击等操作。

  第一点很好理解,ListView就是实现这个功能的。第二点也不难做到,在后面的学习中读者会发现,这非常简单。

 

一个ListView的创建需要3个元素

(1)ListView中的每一列的View。

(2)填入View的数据或者图片等。

(3)连接数据与ListView的适配器。

也就是说,要使用ListView,首先要了解什么是适配器。适配器是一个连接数据和AdapterView(ListView就是一个典型的AdapterView,后面还会学习其他的)的桥梁,通过它能有效地实现数据与AdapterView的分离设置,使AdapterView与数据的绑定更加简便,修改更加方便

Android中提供了很多的Adapter,表4-5列出了常用的几个。

表4-5 常用适配器

Adapter

含义

ArrayAdapter<T>

用来绑定一个数组,支持泛型操作

SimpleAdapter

用来绑定在xml中定义的控件对应的数据

SimpleCursorAdapter

用来绑定游标得到的数据

BaseAdapter

通用的基础适配器

 

 其实适配器还有很多,要注意的是,各种Adapter只不过是转换的方式和能力不一样而已。

 

 ListView使用SimpleAdapter

很多时候需要在列表中展示一些除了文字以外的东西,比如图片等。这时候可以使用SimpleAdapter。SimpleAdapter的使用也非常简单,同时它的功能也非常强大。可以通过它自定义ListView中的item的内容,比如图片、多选框等。

使用simpleAdapter的数据一般都是用HashMap构成的列表,列表的每一节对应ListView的每一行。通过SimpleAdapter的构造函数,将HashMap的每个键的数据映射到布局文件中对应控件上。这个布局文件一般根据自己的需要来自己定义。梳理一下使用SimpleAdapter的步骤。

(1)根据需要定义ListView每行所实现的布局。

(2)定义一个HashMap构成的列表,将数据以键值对的方式存放在里面。

(3)构造SimpleAdapter对象。

(4)将LsitView绑定到SimpleAdapter上。

 

BaseAdapter

  在ListView的使用中,有时候还需要在里面加入按钮等控件,实现单独的操作。也就是说,这个ListView不再只是展示数据,也不仅仅是这一行要来处理用户的操作,而是里面的控件要获得用户的焦点。读者可以试试用SimpleAdapter添加一个按钮到ListView的条目中,会发现可以添加,但是却无法获得焦点,点击操作被ListView的Item所覆盖。这时候最方便的方法就是使用灵活的适配器BaseAdapter了。

   当系统开始绘制ListView的时候,首先调用getCount()方法。得到它的返回值,即ListView的长度。然后系统调用getView()方法,根据这个长度逐一绘制ListView的每一行。也就是说,如果让getCount()返回1,那么只显示一行。而getItem()和getItemId()则在需要处理和取得Adapter中的数据时调用。那么getView如何使用呢?如果有10000行数据,就绘制10000次?这肯定会极大的消耗资源,导致ListView滑动非常的慢,那应该怎么做呢?

 

下面就通过微信的例子说明吧!

下面是布局文件

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical" >
 6 
 7     <ListView
 8         android:id="@+id/listView1"
 9         android:layout_width="match_parent"
10         android:layout_height="match_parent" >
11     </ListView>
12 
13 </LinearLayout>
listview_layout.xml
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="wrap_content"
 5     android:paddingLeft="@dimen/activity_horizontal_margin"
 6     android:paddingRight="@dimen/activity_horizontal_margin"
 7     android:paddingTop="@dimen/activity_horizontal_margin"
 8     android:paddingBottom="@dimen/activity_horizontal_margin"
 9     android:orientation="horizontal" >
10 
11     <ImageView
12         android:id="@+id/face"
13         android:layout_width="60dp"
14         android:layout_height="60dp"
15         android:src="@drawable/houzi" />
16 
17 
18     <LinearLayout
19         android:layout_weight="1"
20         android:layout_width="wrap_content"
21         android:layout_height="wrap_content" 
22         android:layout_margin="5dp"
23         android:orientation="vertical" >
24         
25         <LinearLayout
26             android:layout_weight="1"
27                android:layout_width="match_parent"
28             android:layout_height="wrap_content" 
29                android:layout_marginBottom="3dp"
30             android:orientation="horizontal"  >
31             
32                 <TextView
33                     android:layout_weight="1"
34                     android:id="@+id/name"
35                     android:layout_width="wrap_content"
36                     android:layout_height="wrap_content"
37                     android:textSize="20sp"
38                     android:textColor="#7F7F7F"/>
39                 
40                  <TextView
41                     android:id="@+id/date"
42                     android:layout_width="wrap_content"
43                     android:layout_height="wrap_content"
44                     android:textSize="15sp"
45                     android:textColor="#A9A9A9"/>
46         </LinearLayout>
47         <LinearLayout
48             android:layout_weight="1"
49                android:layout_width="match_parent"
50             android:layout_height="wrap_content" 
51                android:layout_marginBottom="3dp"
52             android:orientation="horizontal"  >
53             <TextView
54                 android:layout_weight="1"
55                 android:id="@+id/content"
56                 android:layout_width="wrap_content"
57                 android:layout_height="wrap_content"
58                 android:textSize="15sp"
59                 android:textColor="#A9A9A9"/>
60             <TextView
61                 android:id="@+id/noRead"
62                 android:layout_width="wrap_content"
63                 android:layout_height="wrap_content"
64                 android:textSize="15sp"
65                 android:text=""
66                 android:textColor="#FF0000"/>
67         </LinearLayout>
68     </LinearLayout>
69 
70    
71 
72 </LinearLayout>
middle2.xml
 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical"
 6     tools:context="com.main.weixin.MainActivity" >
 7 
 8     <!-- 头部 -->
 9     <LinearLayout
10         android:id="@+id/linearLayout1"
11         android:layout_width="match_parent"
12         android:layout_height="wrap_content"
13       >
14         
15         <include layout="@layout/head"/>
16           
17     </LinearLayout>
18 
19     
20     <!-- 中间 -->
21     <LinearLayout
22         android:layout_weight="1"
23         android:layout_width="match_parent"
24         android:layout_height="match_parent">
25         
26           <include layout = "@layout/listview_layout"></include>
27         
28     </LinearLayout>
29 
30     
31     
32     <!-- 尾部 -->
33     <LinearLayout
34         android:layout_width="match_parent"
35         android:layout_height="wrap_content"
36       >
37         
38         <include layout="@layout/bottom"/>
39         
40     </LinearLayout>
41 </LinearLayout>
activity_main.xml

下面是activity主要文件

 1 package com.weixin.entity;
 2 
 3 public class Messages {
 4 
 5     private String face;
 6     private String name;
 7     private String Date;
 8     private String content;
 9     private Integer noRead;
10     
11     public String getFace() {
12         return face;
13     }
14     public void setFace(String face) {
15         this.face = face;
16     }
17     public String getName() {
18         return name;
19     }
20     public void setName(String name) {
21         this.name = name;
22     }
23     public String getDate() {
24         return Date;
25     }
26     public void setDate(String date) {
27         Date = date;
28     }
29     public String getContent() {
30         return content;
31     }
32     public void setContent(String content) {
33         this.content = content;
34     }
35     public Integer getNoRead() {
36         return noRead;
37     }
38     public void setNoRead(Integer noRead) {
39         this.noRead = noRead;
40     }
41     
42     
43 
44 }
Message
  1 package com.main.weixin;
  2 
  3 import java.util.ArrayList;
  4 import java.util.HashMap;
  5 import java.util.List;
  6 import java.util.Map;
  7 
  8 import com.database.weixin.MyDatabaseOpenHelper;
  9 import com.weixin.entity.Messages;
 10 
 11 import android.app.Activity;
 12 import android.os.Bundle;
 13 import android.util.Log;
 14 import android.view.LayoutInflater;
 15 import android.view.Menu;
 16 import android.view.MenuItem;
 17 import android.view.View;
 18 import android.view.ViewGroup;
 19 import android.view.Window;
 20 import android.widget.AdapterView;
 21 import android.widget.AdapterView.OnItemClickListener;
 22 import android.widget.BaseAdapter;
 23 import android.widget.ListView;
 24 import android.widget.SimpleAdapter;
 25 import android.widget.TextView;
 26 
 27 
 28 public class MainActivity extends Activity {
 29     
 30     private SimpleAdapter sa;
 31     private BaseAdapter ba;
 32     private ListView lv;
 33     private List<Messages> listMessage = new ArrayList<Messages>();
 34     private List<Map<String,Object>> listMessage2 = new ArrayList<Map<String,Object>>();
 35 
 36     @Override
 37     protected void onCreate(Bundle savedInstanceState) {
 38         super.onCreate(savedInstanceState);
 39         requestWindowFeature(Window.FEATURE_NO_TITLE);
 40         setContentView(R.layout.activity_main);
 41         
 42         
 43       //模拟读取数据库或者互联网
 44         for(int i=0 ; i<100 ; i++){
 45             Messages message = new Messages();
 46             message.setFace("houzi");
 47             message.setName("孙行者"+i);
 48             message.setDate("昨天");
 49             message.setContent("有空吗?今晚一起吃饭");
 50             message.setNoRead(i);
 51             listMessage.add(message);//方法一
 52             
 53             
 54        /*     //定义一个界面与数据混合体,一个Item代表一行记录
 55             Map<String,Object> item = new HashMap<String,Object>();
 56             //一行多个空件
 57             item.put("face", R.drawable.houzi);
 58             item.put("name", "孙行者"+i);
 59             item.put("date", "昨天");
 60             item.put("content", "有空吗?今晚一起吃饭");
 61             listMessage2.add(item);*/
 62             
 63         }
 64         
 65         lv = (ListView) findViewById(R.id.listView1);
 66         
 67         /*   sa = new SimpleAdapter(this,
 68                 listMessage2, //data 不仅是数据,而是数据与界面高耦合的混合体
 69                 R.layout.middle1,
 70                 new String[]{"face","name","date","content"}, 
 71                 new int[]{R.id.face,R.id.name,R.id.date,R.id.content});
 72         
 73         lv.setAdapter(sa);
 74         
 75         //添加事件
 76         lv.setOnItemClickListener(new OnItemClickListener(){
 77 
 78             @Override
 79             public void onItemClick(AdapterView<?> parent, View view,
 80                     int position, long id) {
 81                 
 82                 Map<String,Object> item =listMessage2.get(position);
 83                 item.put("name", "行者孙"+position);
 84                 sa.notifyDataSetChanged();
 85             }
 86             
 87         }); */
 88         
 89         
 90     //简单理解为VC绑在一起
 91         ba = new BaseAdapter(){
 92 
 93             //返回记录数目
 94             @Override
 95             public int getCount() {
 96                 
 97                 return listMessage.size();
 98                 
 99             }
100             
101             //每一个item项,返回一次界面
102             @Override
103             public View getView(int position, View convertView, ViewGroup parent) {
104                 View view ;
105                 
106                 //布局不变,数据变
107                 
108                 
109                 //如果缓存为空,我们生成新的布局作为1个item
110                 if(convertView == null){
111                     Log.i("info:", "没有缓存,重新生成"+position);
112                     LayoutInflater inflater = MainActivity.this.getLayoutInflater();
113                     
114 
115                         //因为getView()返回的对象,adapter会自动赋给ListView
116                         view = inflater.inflate(R.layout.middle2, null);
117                         
118                 }else{
119                     Log.i("info:", "有缓存,不需要重新生成"+position);
120                     view = convertView;
121                     
122                 }
123                 
124                 Messages m = listMessage.get(position);
125                 Integer noRead = m.getNoRead();
126                 
127                 TextView tv_name = (TextView) view.findViewById(R.id.name);
128                 tv_name.setText(m.getName());
129                 
130                 TextView tv_date = (TextView) view.findViewById(R.id.date);
131                 tv_date.setText(m.getDate());
132                 
133                 TextView tv_content = (TextView) view.findViewById(R.id.content);
134                 tv_content.setText(m.getContent());
135                 
136                 System.out.println(noRead);
137                 
138                 if( noRead !=0){
139                     TextView tv_noRead = (TextView) view.findViewById(R.id.noRead);
140                     //这里的setText()方法接收的是一个字符串类型,而你给了一个Integer类型给它,所以报错了,这里需要把Integer类型转为String类型即可
141                     tv_noRead.setText(noRead.toString());
142                 
143                 }
144                 
145                 return view ;
146                 
147             }
148    
149             @Override
150             public Object getItem(int position) {
151                 return null;
152             }
153 
154             @Override
155             public long getItemId(int position) {
156                 return 0;
157             }
158 
159             
160         };
161         lv.setAdapter(ba);
162         
163        //添加事件
164         lv.setOnItemClickListener(new OnItemClickListener(){
165 
166             @Override
167             public void onItemClick(AdapterView<?> parent, View view,
168                     int position, long id) {
169                 Messages message = listMessage.get(position);
170                 if(message.getNoRead()!=0){
171                     
172                     message.setName("行者孙"+position);
173                     message.setNoRead(0);
174                     
175                     view.findViewById(R.id.noRead).setVisibility(View.INVISIBLE);
176                     
177                 }else{
178                     message.setName("孙行者"+position);
179                 }
180                 
181                 ba.notifyDataSetChanged();//
182             }
183             
184         });
185     }
186 
187 
188     @Override
189     public boolean onCreateOptionsMenu(Menu menu) {
190         getMenuInflater().inflate(R.menu.main, menu);
191         return true;
192     }
193 
194     @Override
195     public boolean onOptionsItemSelected(MenuItem item) {
196         int id = item.getItemId();
197         if (id == R.id.action_settings) {
198             return true;
199         }
200         return super.onOptionsItemSelected(item);
201     }
202 }

效果如下:

 

convertView相当于一个缓存,开始为0,当有条目变为不可见,它缓存了它的数据,后面再出来的条目只需要更新数据就可以了,这样大大节省了系统资料的开销。

posted on 2016-11-29 15:49  根坤  阅读(201)  评论(0编辑  收藏  举报

导航