Android界面中有时候需要显示稍微复杂的界面时,就需要我们自定义一个adapter,而此adapter就要继承BaseAdapter,重新其中的方法.

        Android中Adapter类其实就是把数据源绑定到指定的View上,然后再返回该View,而返回来的这个View就是ListView中的某一 行item。这里返回来的View正是由我们的Adapter中的getView方法返回的。这样就会容易理解数据是怎样一条一条显示在ListView 中的。
       在完成这篇文章中的例子之后,我思考了很长时间,关于重写一个adapter,这其中真的有很多讲究,遇到一处不懂的都会查阅很长时间,但也不能保证我已经把其中的重中之重已经找完了,只要你想延伸都可以发现其中的无限.....
       问题1:为什么我们要重写一个adapter?
       问题2:android中这么多adapter,什么情况下该重写哪一个adapter(ArrayAdapter/SimpleAdapter/SimpleCursorAdapter...)?
       问题3:我们重写的adapter为什么是一个内部类,是否建议把adapter做成一个内部类?
       问题4:理解应用中的数据源一般都会用一个Map类型的List,有何意途?
       问题5:通过adapter是怎样做到把一条一条的item放到ListView中的?
       问题6:理解重写adapter时,重写的几个方法(getCount()/getItem()/getItemId()/getView())?
       问题7:理解ListView使用adapter的机制
      
 
案例概览步骤:
1)创建2个layout,一个是界面顶部的显示,一个是ListView中的内容
   1.1)ListView_header.xml(注:自我感觉界面中的控件的位置摆放与layout_width/layout_height/orientation/gravity/layout_gravity的属性设置关系非常大,一定要注意每个属性的用法)
 
<?xml version="1.0" encoding="UTF-8"?>
<!-- 第一个LinearLayout,充当父容器,要包揽两行,因此设置其 android:orientation为    纵向-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">
   
    <!-- 第二个LinearLayout
    android:gravity 表示该LinearLayout中的类容相对于该LinearLayout 水平居中
    android:layout_gravity 表示的是该LinearLayout相对于它上面的父容器(这里是第一个LinearLayout)水平居中
    -->
    <LinearLayout android:id="@+id/toprow"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:gravity="center_horizontal">
       
     <TextView android:id="@+id/quna"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:textColor="#ff9966ff"
         android:textSize="25dp"
         android:text="@string/places"/>
    
     <!-- 用一个图片按钮 -->
     <ImageButton android:id="@+id/goBtn"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:src="@drawable/quna"/>
    </LinearLayout>
   
    <TextView android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="@string/placesList"
         android:textColor="#ff9966ff"
         android:textSize="20dp"/>
   
    <ListView android:id="@+id/list_places"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>
   
</LinearLayout>
 
1.2)listview_item.xml
 
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" //此属性的设置非常重要,决定里面的控件横向摆放
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <!-- android:layout_margin设置图片与旁边文章的距离 -->
    <ImageView android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"/>
    <LinearLayout android:orientation="vertical" //也很重要决定里面的两个textview竖着放
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <TextView android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ff3399ff"
            android:textSize="20dp"/>
        <TextView android:id="@+id/info"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ff3399ff"
            android:textSize="13dp"/>
    </LinearLayout>
    <!-- 注意此处button的属性android:layout_gravity的用法 ,这里设置了都没效果
    这里不是很理解为什么要在加一个LinearLayout,里面的button才可以居右??
    而且LinearLayout的width必须为fill_parent才可以
    -->
    <LinearLayout android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        >
    <Button android:id="@+id/viewBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/btn_select"
        android:layout_gravity="bottom|right"/>
   
    </LinearLayout>
</LinearLayout>
 
2)、写java class,开发activity(建一个class继承Activity,添加click事件的时候还要实现onClickListener接口)
       2.1)  重写onCreate方法----------------------------------------------->
 
         private ListView listView;
         private ImageButton goBtn;
         private List<Map<String, Object>> testData;
      protected void onCreate(Bundle savedInstanceState) {
                      super.onCreate(savedInstanceState);
                      setContentView(R.layout.listview_header);//这里运行该项目的时候,让其显示listview_header.xml界面(layout),然后再将listview要显示的item项加到里面
                      //获得listview_header.xml中的ListView控件
                      listView = (ListView) findViewById(R.id.list_places);
                      //获得imageButton给它添加click事件
                      goBtn = (ImageButton) findViewById(R.id.goBtn);
                      goBtn.setOnClickListener(new OnClickListener() {
                                 //这里只是做出了简单的弹出框
                                @Override
                                 public void onClick(View v) {
                                            new AlertDialog.Builder(BaseAdapterTest2.this).setTitle("想去的国家:")
                                                                                  .setMessage("i want to go France")
                                                                                  .setPositiveButton("确定", null).sho();
                                  }
                                 });
  
                     //数据源
                     testData = buildData();
                     MyAdapter adapter = new MyAdapter(this);
                     //通过setAdapter而把数据绑定到ListView中
                     listView.setAdapter(adapter); 
           }
 
      2.2)创建数据,注意这里为什么要是Map类型的List集合
            private List<Map<String, Object>> buildData(){
                        List<Map<String, Object>> data = new ArrayList<Map<String,Object>>();
                        Map<String, Object> map = new HashMap<String, Object>();
                        map.put("title", "中国");
                       map.put("info", "China");
                       map.put("image", R.drawable.p6);
                       data.add(map);
  
                       map = new HashMap<String, Object>();
                       map.put("title", "英国");
                       map.put("info", "England");
                       map.put("image", R.drawable.p7);
                       data.add(map);
  
                       map = new HashMap<String, Object>();
                       map.put("title", "美国");
                       map.put("info", "America");
                       map.put("image", R.drawable.p9);
  
                        map = new HashMap<String, Object>();
                        map.put("title", "荷兰");
                        map.put("info", "Dutch");
                        map.put("image", R.drawable.p9);
                       data.add(map);
  
                       map = new HashMap<String, Object>();
                       map.put("title", "新西兰");
                       map.put("info", "New Zealand");
                       map.put("image", R.drawable.p7);
                       data.add(map);
 
                       data.add(map);
  
                       return data;
           }
 
         2.3)写自定义adapter(它是一个内部类,继承自BaseAdapter,并不确定是否自定义的adapter一般都是继承它),尤其注意其中的几个方法
           public class MyAdapter extends BaseAdapter{
                       private LayoutInflater inflater;//这个一定要懂它的用法及作用
  
                      //构造函数:要理解(这里构造方法的意义非常强大,你也可以传一个数据集合的参数,可以根据需要来传参数)
                      public MyAdapter(Context context){
                                 this.inflater = LayoutInflater.from(context);
                      }
  
                     //这里的getCount方法是程序在加载显示到ui上时就要先读取的,这里获得的值决定了listview显示多少行
                     @Override
                     public int getCount() {
                               //在实际应用中,此处的返回值是由从数据库中查询出来的数据的总条数
                               return testData.size();
                     }
                    
                     //根据ListView所在位置返回View
                    @Override
                     public Object getItem(int position) {
                                // TODO Auto-generated method stub
                               return this.testData.get(position);
                     }
 
                      //根据ListView位置得到数据源集合中的Id
                     @Override
                     public long getItemId(int position) {
                               // TODO Auto-generated method stub
                               return position;
                     }
                    //重写adapter最重要的就是重写此方法,此方法也是决定listview界面的样式的
                    @Override
                    public View getView(int position, View convertView, ViewGroup parent) {
                                    //有很多例子中都用到这个holder,理解下??
                               ViewHolder holder = null;
                                //思考这里为何要判断convertView是否为空  ??
                                if(convertView == null){
                                         holder = new ViewHolder();
    
                                         //把vlist layout转换成View【LayoutInflater的作用】
                                         convertView = inflater.inflate(R.layout.vlist, null);
                                         //通过上面layout得到的view来获取里面的具体控件
                                         holder.image = (ImageView) convertView.findViewById(R.id.image);
                                         holder.title = (TextView) convertView.findViewById(R.id.title);
                                         holder.info = (TextView) convertView.findViewById(R.id.info);
                                         holder.viewBtn = (Button) convertView.findViewById(R.id.viewBtn);
                                         //不懂这里setTag什么意思??
                                         convertView.setTag(holder);
                               }
                               else{
                                          holder = (ViewHolder) convertView.getTag();
                                }
                            //这里testData.get(position).get("title1")),其实就是从list集合(testData)中取出对应索引的map,然后再根据键值对取值
                            holder.image.setBackgroundResource((Integer) testData.get(position).get("image1"));
                            holder.title.setText((String) testData.get(position).get("title1"));
                            holder.info.setText((String) testData.get(position).get("info1"));
                            //为listview上的button添加click监听
                            holder.viewBtn.setOnClickListener(new View.OnClickListener() {
                                       @Override
                                       public void onClick(View v) {
                                                   .....
                                       }
                            });
   
              return convertView;
  }
  
 }
 
        到此,整个案例的关键部分已经全部出来了,做的过程中有很多地方没有想通也都做有注释,做完以后,多揣摩了几遍才将就理解,嘿嘿
重点提出一个疑问:不能确定是否在onCreate方法中的 new Adapter,在里面表面上看是只调用了一次而进入自定义Adapter中调用(其实也没有直接调用,自己想的它可能有一个自己的内部机制,每new完一个Adapter就直接调用getCount/getView方法吗)它里面的方法 ,调用一次就会绘制一个ListView中的一个item项,那么有很多条item的时候,它是否要那样循环调用很多次呢??
       getView方法中的参数,convertview那块。在初始化的时候,每显示一行item项都会调用一次getView方法但每次调用的时候convertview为null(因为还没有旧的view);
如果屏幕移动了之后,并且导致某些item项跑到屏幕外面,此时如果还有新的item需要产生,则这些item显示时调用的getView方法中的
convertview就不为null,而是那些移出到屏幕之外的view,我们所要做的就是将需要显示的item项填充到移除屏幕外的(旧的)view
中去,注意【convertview为null的不仅仅是初始化显示的那些item,还有一些是已经开始移入屏幕但还没有view被回收的那些
item】。
  
运行结果:
 

Android中Adapter之BaseAdapter使用的更多相关文章

  1. Android中Adapter总结

    根据一个制作列表的程序开始练手,结果就出现了学习安卓的第一个代码问题 运行程序发现,虽然报错,但是可以成功运行程序. Android中Adapter功能为 显示ListView,最常用的有ArrayA ...

  2. Android中Adapter和Bridge模式理解和应用

    一 Adapter模式 意图: 将一个类的接口转换成客户希望的另外一个接口. Adapter模式使得原本由于接口不兼容而不能在一起工作的那些类可以在一起工作. 适用性: 使用一个已存在的类,而它的接口 ...

  3. android 中listview之BaseAdapter的使用

    Listview控件不像其他安卓控件那种直接拖拽到界面上就能用,而是采用类似J2EE中的MVC模型的方式使用,需要通过适配器将某种样式的数据或控件添加到其上而使用. MVC模型实现原理是 数据模型M( ...

  4. Android中ListView通过BaseAdapter实现数据的绑定

    1. public class ListFiles extends Activity { ListView Listview=null; protected void onCreate(Bundle ...

  5. android中Adapter适配器的讲解

    Adapter(适配器的讲解) 适配器就我自己来看,我觉得这是一个非常重要的知识点,Adapter是用来帮助填出数据的中间桥梁,简单点说吧:将各种数据以合适的形式显示在View中给用户看.Adapte ...

  6. Android 中万能的 BaseAdapter(Spinner,ListView,GridView) 的使用!

    大家好!今天给大家讲解一下BaseAdapter(基础适配器)的用法,适配器的作用主要是用来给诸如(Spinner,ListView,GridView)来填充数据的.而(Spinner,ListVie ...

  7. Android中Adapter类的使用 “Adapter”

    Adapter用来把数据绑定到扩展了AdapterView类的视图组(例如:ListView或Gallery).Adapter负责创建代表所绑定父视图中的底层数据的子视图. 可以创建自己的Adapte ...

  8. Android中的自定义Adapter(继承自BaseAdapter)——与系统Adapter的调用方法一致——含ViewHolder显示效率的优化(转)

    Android中很多地方使用的是适配器(Adapter)机制,那我们就要好好把这个Adapter利用起来,并且用出自己的特色,来符合我们自行设计的需要喽~~~ 下面先上一个例子,是使用ViewHold ...

  9. 使用具体解释及源代码解析Android中的Adapter、BaseAdapter、ArrayAdapter、SimpleAdapter和SimpleCursorAdapter

    Adapter相当于一个数据源,能够给AdapterView提供数据.并依据数据创建相应的UI.能够通过调用AdapterView的setAdapter方法使得AdapterView将Adapter作 ...

随机推荐

  1. mysql乱码以及Data too long for column全解(最完整实用版)

    今天系统升级,开发.测试说本地环境.测试环境都没有问题,都用ssh client升的,演示环境报错了Data too long for column. 仔细检查了下,表字符集都是utf-8,目测长度肯 ...

  2. js的alert和confirm美化

    --前言-- window对象的alert和confirm标准方法在不同浏览器的显示效果不太相同,有个相同点是都不是很美观.我们的想法是使用js和css分别仿照它们,提供另一套函数,使在不同浏览器的有 ...

  3. JS数组的forEach方法(兼容所有浏览器)

    //->自己在内置类的原型上扩展一个myForEach来处理forEach不兼容的问题//callBack:回调函数,遍历数组中的一项,就要执行一次callBack//context:改变cal ...

  4. Oracle计算时间差函数

    两个Date类型字段:START_DATE,END_DATE,计算这两个日期的时间差(分别以天,小时,分钟,秒,毫秒): 天: ROUND(TO_NUMBER(END_DATE - START_DAT ...

  5. eclipse智能提示

    原文地址:http://www.cnblogs.com/myitm/archive/2010/12/17/1909194.html Windows→Preferences→Java→Editor→Co ...

  6. mysql基础操作学习笔记(2)----索引

    为什么要创建索引?     在此本人也带着相同的疑问,能够解释的仅仅是:为了减少数据库查询时所需要的速度.如果正常查询和索引查询所需时间相差很多倍时我们自然是需要索引的了. 想要知道结果,只能等我学得 ...

  7. 叶金荣:MySQL通用优化技巧

    转自:http://mp.weixin.qq.com/s?__biz=MjM5NDE0MjI4MA==&mid=208777870&idx=1&sn=6efddd6283e4d ...

  8. eclipse发布项目时,会自动还原server.xml和content.xml文件

    因为Tomcat的端口冲突,导致eclipse发布项目时,失败.于是到server.xml文件中修改端口,重启使用eclipse发布项目,发现依然报端口冲突的错误,其原因时,刚才对server.xml ...

  9. MongoDB 存储引擎Wiredtiger原理剖析

    今天开始看MongoDB 3.2的文档,发现了这么两句话 Support for Multiple Storage Engines MongoDB supports multiple storage ...

  10. EXECL文件导入数据库

    Execl数据导入数据库: 注意事项:execl中的列名与列数要与数据库的列名和列数一致.值类型一致,列名不一致的话可在导入的时候,给字段起别名,确定保持一致 v 界面代码: <div> ...