Android ListView之BaseAdapter

  话说开发用了各种Adapter之后感觉用的最舒服的还是BaseAdapter,尽管使用起来比其他适配器有些麻烦,但是使用它却能实现很多自己喜欢的列表布局,比如ListView、GridView、Gallery、Spinner等等。它是直接继承自接口类Adapter的,使用BaseAdapter时需要重写很多方法,其中最重要的当属getView,因为这会涉及到ListView优化等问题.

  BaseAdapter与其他Adapter有些不一样,其他的Adapter可以直接在其构造方法中进行数据的设置,比如:

1 SimpleAdapter adapter =         new SimpleAdapter(this, getData(), R.layout.list_item, new String[]{"img","title","info",new int[]{R.id.img, R.id.title, R.id.info}});

  在BaseAdapter中,需要实现一个继承自BaseAdapter的类,并且重写里面的很多方法,例如:

 1 class MyAdapter extends BaseAdapter
 2     {
 3         private Context context;
 4         public MyAdapter(Context context)
 5         {
 6             this.context = context;
 7         }
 8         @Override
 9         public int getCount() {
10             // How many items are in the data set represented by this Adapter.(在此适配器中所代表的数据集中的条目数)
11             return 0;
12         }
13
14         @Override
15         public Object getItem(int position) {
16             // Get the data item associated with the specified position in the data set.(获取数据集中与指定索引对应的数据项)
17             return null;
18         }
19
20         @Override
21         public long getItemId(int position) {
22             // Get the row id associated with the specified position in the list.(取在列表中与指定索引对应的行id)
23             return 0;
24         }
25
26         @Override
27         public View getView(int position, View convertView, ViewGroup parent) {
28             // Get a View that displays the data at the specified position in the data set.
29             return null;
30         }
31
32     }

  这里面没什么难度,但是这个getView方法必须好好处理,也是最麻烦的。

  

  第一种:没有任何处理,不建议这样写。

  如果数据量少看将就,但是如果列表项数据量很大的时候,会每次都重新创建View,设置资源,严重影响性能,所以从一开始就不要用这种方式。

 1 @Override
 2         public View getView(int position, View convertView, ViewGroup parent) {
 3             View item = mInflater.inflate(R.layout.list_item, null);
 4             ImageView img = (ImageView)item.findViewById(R.id.img)
 5             TextView title = (TextView)item.findViewById(R.id.title);
 6             TextView info = (TextView)item.findViewById(R.id.info);
 7             img.setImageResource(R.drawable.ic_launcher);
 8             title.setText("Hello");
 9             info.setText("world");
10
11             return item;
12         }

  

  第二种:ListView优化。通过缓存convertView,这种利用缓存contentView的方式可以判断如果缓存中不存在View才创建View,

  如果已经存在可以利用缓存中的View,提升了性能。

 1 public View getView(int position, View convertView, ViewGroup parent) {
 2             if(convertView == null)
 3             {
 4                 convertView = mInflater.inflate(R.layout.list_item, null);
 5             }
 6
 7             ImageView img = (ImageView)convertView.findViewById(R.id.img)
 8             TextView title = (TextView)convertView.findViewById(R.id.title);
 9             TextView info = (TextView)ConvertView.findViewById(R.id.info);
10             img.setImageResource(R.drawable.ic_launcher);
11             title.setText("Hello");
12             info.setText("world");
13
14             return convertView;
15         }

  

  

  第三种:ListView优化。通过convertView+ViewHolder来实现,ViewHolder就是一个静态类,使用 ViewHolder 的关键好处是缓存了显示数据的视图(View),加快了 UI 的响应速度。

  当我们判断 convertView == null  的时候,如果为空,就会根据设计好的List的Item布局(XML),来为convertView赋值,并生成一个viewHolder来绑定converView里面的各个View控件(XML布局里面的那些控件)。再用convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。(看下面代码中)

  如果convertView不为空的时候,就会直接用convertView的getTag(),来获得一个ViewHolder。

 1 //在外面先定义,ViewHolder静态类
 2     static class ViewHolder
 3     {
 4         public ImageView img;
 5         public TextView title;
 6         public TextView info;
 7     }
 8 //然后重写getView
 9         @Override
10         public View getView(int position, View convertView, ViewGroup parent) {
11             ViewHolder holder;
12             if(convertView == null)
13             {
14                 holder = new ViewHolder();
15                 convertView = mInflater.inflate(R.layout.list_item, null);
16                 holder.img = (ImageView)item.findViewById(R.id.img)
17                 holder.title = (TextView)item.findViewById(R.id.title);
18                 holder.info = (TextView)item.findViewById(R.id.info);
19                 convertView.setTag(holder);
20             }else
21             {
22                 holder = (ViewHolder)convertView.getTag();
23                 holder.img.setImageResource(R.drawable.ic_launcher);
24                 holder.title.setText("Hello");
25                 holder.info.setText("World");
26             }
27
28             return convertView;
29         }

  

  到这里,可能会有人问ViewHolder静态类结合缓存convertView与直接使用convertView有什么区别吗,是否重复了?

  在这里,官方给出了解释******提升Adapter的两种方法:

  To work efficiently the adapter implemented here uses two techniques:
  -It reuses the convertView passed to getView() to avoid inflating View when it is not necessary

  (译:重用缓存convertView传递给getView()方法来避免填充不必要的视图)
  -It uses the ViewHolder pattern to avoid calling findViewById() when it is not necessary

  (译:使用ViewHolder模式来避免没有必要的调用findViewById():因为太多的findViewById也会影响性能)
  ViewHolder类的作用
  -The ViewHolder pattern consists in storing a data structure in the tag of the view
  returned by getView().This data structures contains references to the views we want to bind data to,
  thus avoiding calling to findViewById() every time getView() is invoked

  (译:ViewHolder模式通过getView()方法返回的视图的标签(Tag)中存储一个数据结构,这个数据结构包含了指向我们

  要绑定数据的视图的引用,从而避免每次调用getView()的时候调用findViewById().

  实例:用BaseAdapter来自定义ListView布局:

  main.xml

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="fill_parent"
 4     android:layout_height="fill_parent"
 5     android:orientation="vertical" >
 6
 7     <ListView
 8         android:id="@+id/lv"
 9         android:layout_width="fill_parent"
10         android:layout_height="wrap_content"
11         android:fastScrollEnabled="true"
12         />
13
14 </LinearLayout>

  list_item.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="match_parent"
 5     android:orientation="horizontal" >
 6
 7     <ImageView
 8         android:id="@+id/img"
 9         android:layout_width="wrap_content"
10         android:layout_height="wrap_content"
11         />
12     <LinearLayout
13         android:layout_width="fill_parent"
14         android:layout_height="wrap_content"
15         android:orientation="vertical"
16         >
17         <TextView
18             android:id="@+id/tv"
19             android:layout_width="wrap_content"
20             android:layout_height="wrap_content"
21             android:textSize="20sp"
22         />
23         <TextView
24             android:id="@+id/info"
25             android:layout_width="wrap_content"
26             android:layout_height="wrap_content"
27             android:textSize="14sp"
28             />
29     </LinearLayout>
30
31
32 </LinearLayout>

  Activity

  1 package com.loulijun.demo17;
  2
  3 import java.util.ArrayList;
  4 import java.util.HashMap;
  5 import java.util.List;
  6 import java.util.Map;
  7
  8 import android.app.Activity;
  9 import android.content.Context;
 10 import android.os.Bundle;
 11 import android.view.LayoutInflater;
 12 import android.view.View;
 13 import android.view.ViewGroup;
 14 import android.widget.BaseAdapter;
 15 import android.widget.ImageView;
 16 import android.widget.ListView;
 17 import android.widget.TextView;
 18
 19 public class Demo17Activity extends Activity {
 20     private ListView lv;
 21     private List<Map<String, Object>> data;
 22     @Override
 23     public void onCreate(Bundle savedInstanceState) {
 24         super.onCreate(savedInstanceState);
 25         setContentView(R.layout.main);
 26         lv = (ListView)findViewById(R.id.lv);
 27         //获取将要绑定的数据设置到data中
 28         data = getData();
 29         MyAdapter adapter = new MyAdapter(this);
 30         lv.setAdapter(adapter);
 31     }
 32
 33     private List<Map<String, Object>> getData()
 34     {
 35         List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
 36         Map<String, Object> map;
 37         for(int i=0;i<10;i++)
 38         {
 39             map = new HashMap<String, Object>();
 40             map.put("img", R.drawable.ic_launcher);
 41             map.put("title", "跆拳道");
 42             map.put("info", "快乐源于生活...");
 43             list.add(map);
 44         }
 45         return list;
 46     }
 47
 48     //ViewHolder静态类
 49     static class ViewHolder
 50     {
 51         public ImageView img;
 52         public TextView title;
 53         public TextView info;
 54     }
 55
 56     public class MyAdapter extends BaseAdapter
 57     {
 58         private LayoutInflater mInflater = null;
 59         private MyAdapter(Context context)
 60         {
 61             //根据context上下文加载布局,这里的是Demo17Activity本身,即this
 62             this.mInflater = LayoutInflater.from(context);
 63         }
 64
 65         @Override
 66         public int getCount() {
 67             //How many items are in the data set represented by this Adapter.
 68             //在此适配器中所代表的数据集中的条目数
 69             return data.size();
 70         }
 71
 72         @Override
 73         public Object getItem(int position) {
 74             // Get the data item associated with the specified position in the data set.
 75             //获取数据集中与指定索引对应的数据项
 76             return position;
 77         }
 78
 79         @Override
 80         public long getItemId(int position) {
 81             //Get the row id associated with the specified position in the list.
 82             //获取在列表中与指定索引对应的行id
 83             return position;
 84         }
 85
 86         //Get a View that displays the data at the specified position in the data set.
 87         //获取一个在数据集中指定索引的视图来显示数据
 88         @Override
 89         public View getView(int position, View convertView, ViewGroup parent) {
 90             ViewHolder holder = null;
 91             //如果缓存convertView为空,则需要创建View
 92             if(convertView == null)
 93             {
 94                 holder = new ViewHolder();
 95                 //根据自定义的Item布局加载布局
 96                 convertView = mInflater.inflate(R.layout.list_item, null);
 97                 holder.img = (ImageView)convertView.findViewById(R.id.img);
 98                 holder.title = (TextView)convertView.findViewById(R.id.tv);
 99                 holder.info = (TextView)convertView.findViewById(R.id.info);
100                 //将设置好的布局保存到缓存中,并将其设置在Tag里,以便后面方便取出Tag
101                 convertView.setTag(holder);
102             }else
103             {
104                 holder = (ViewHolder)convertView.getTag();
105             }
106             holder.img.setBackgroundResource((Integer)data.get(position).get("img"));
107             holder.title.setText((String)data.get(position).get("title"));
108             holder.info.setText((String)data.get(position).get("info"));
109
110             return convertView;
111         }
112
113     }
114 }

  运行结果如下:

  

时间: 2024-09-29 15:41:04

Android ListView之BaseAdapter的相关文章

Android ListView使用BaseAdapter与ListView的优化 (转至 http://www.open-open.com/lib/view/open1339485728006.html)

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

Android ListView使用BaseAdapter与ListView的优化

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

android ListView 和 BaseAdapter 应用

步聚: 1.建立ListView对象:--(作用:绑定Adapter呈现数据) 2.建立ListView实现的Item栏位.xml布局:--(作用:实现ListView的栏位布局) 3.建立Item.xml 的View数据实例(类):--(作用:实现Item栏位数据接口) 4.继承BaseAdapter建立MyAdapter类class:--(作用:封装ListView的.xml布局与Item数据) 5.当然还要作更多的操作,这里例出简洁的方法: adapter实现: 1 private cla

android ListView 自定义 BaseAdapter

先上效果图 由上面的效果图可以看出:页面中的LISTVIEW的每一项,都是由两个TEXTVIEW组成,初始化的时候,只显示第一个TEXTVIEW,在这里我们成为标题,而内容部分的setVisible属性为"GONE".为Ite添加onClick监听器,在每次点击的时候,显示内容部分,这里需要调用BaseAdapter的notifyDataSetChanged()进行刷新显示. 代码部分: 1 class MyLayout extends LinearLayout { 2 3 priva

android ListView之BaseAdapter的使用方式

通常在使用自己定义适配器的时候,我们都会掌握一种固定的模式.充分利用convertView+缓存的方式. private ArrayList<ListBean> list ; private LayoutInflater mInflater; public DetailListAdapter(Context context,ArrayList<ListBean> list){ this.list=list; mInflater = LayoutInflater.from(conte

Android——ListView布局+适配器(三)

Android--ListView布局+适配器(三) package com.example.administrator.newstop; import android.os.Bundle; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import andro

Android——ListView多布局+适配器(二)

Android--ListView多布局+适配器(二) <span style="font-size:18px;">package com.example.administrator.newstop.entity; /** * Created by Administrator on 2016/8/4. */ public class News { private String title; private String pubDate; private int img; p

[转]Android ListView最佳处理方式,ListView拖动防重复数据显示,单击响应子控件

Android ListView最佳处理方式,ListView拖动防重复数据显示,单击响应子控件. 1.为了防止拖动ListView时,在列表末尾重复数据显示.需要加入 HashMap<Integer,View> lmap = new HashMap<Integer,View>();其中Integer为列表位置,View为子项视图,加入数据前首先if (lmap.get(position)==null) ,满足条件时,加入lmap.put(position, convertView

android listview级联三菜单选择地区,本地数据库sqlite级联地区,item选中不变色

前言:因为找了N多网上的资源都没有好的解决方案,别人都是只给思路没给具体源码,真TMD纠结,干嘛求别人,自己动手才是真,最痛恨那些所谓大牛的作风,给了点点代码就让别人去想,你让我们这种小白情何于堪!!!!!!此例是基于listview来实现本地sqlite实现的! 二话不说,程序猿求的是有图有真相有源码!大家下载后有什么问题可以找到本人:QQ508181017 核心代码如下 1.数据库操作类 package com.icq.demo.db; import java.util.ArrayList;