• 连接AdapterView视图和数据源的桥梁:Adapter适配器(2)


      BaseAdapter是一种原生态的适配器,它是一个抽象类,一般使用它来实现自定义的适配器,当需要适配大量的数据时,为了节省手机的内存,往往会定义一个类继承它,从而优化内存的使用,使用在ListView、Spinner的内存效率优化。

      查询Android官方文档可知BaseAdapter的类定义

    BaseAdapter是直接继承Java中顶级类Object类,同时它实现了ListAdapter和SpinnerAdapter接口。BaseAdapter的常用直接子类有ArrayAdapter<T>、CursorAdapter(抽象类)和SimpleAdapter,常用间接子类有ResourceCursorAdapter(抽象类)和SimpleCursorAdapter。

      一般定义一个类,它继承了BaseAdapter,同时会重写BaseAdapter的四个重要方法:

      1.public int getCount()  返回BaseAdapter适配的数据项个数

      2.public Object getItem(int position)  返回BaseAdapter适配的第postion个数据项的数据

      3.public long getItemId(int position)  返回BaseAdapter开始适配数据项的序号

      4.public View getView(int position, View convertView, ViewGroup parent)  返回BaseAdapter创建的某一个数据项

        

      BaseAdapter的使用一般在于它的优化,即重写getView()方法采用的不用方式,一般有三种写法:

      1.逗比式:未进行任何的优化,按一般思路来重写,当数据量不大,没有什么大问题,一旦数据量比较大时,严重浪费内存同时效率特别低。

      源码:

     1 @Override
     2     public View getView(int position, View convertView, ViewGroup parent) {
     3         View view = null;
     4 
     5         // 将布局文件转化为View对象,通过View对象获取需要设置数据的UI组件对象(两种方法)
     6         // view =LayoutInflater.from(context).inflate(R.layout.item_layout,null);
     7         view = LayoutInflater.from(context).inflate(R.layout.item_layout,
     8                 parent, false);
     9         ImageView image = (ImageView) view.findViewById(R.id.image);
    10         TextView title = (TextView) view.findViewById(R.id.title);
    11         TextView content = (TextView) view.findViewById(R.id.content);
    12 
    13         // 获取该position数据项要显示的数据
    14         Map<String, Object> map = (Map<String, Object>) getItem(position);
    15 
    16         // 设置数据
    17         image.setImageResource((Integer) map.get("image"));
    18         title.setText(map.get("title").toString());
    19         content.setText(map.get("content").toString());
    20 
    21         // 返回第position项的数据项视图
    22         return view;
    23     }

      2.一般式:在1的基础上进行优化,主要优化点在于,利用了方法中的convertView参数,这个参数是系统缓存的View视图,每次调用getView()方法创建View对象时,先判断是否convertView对象是否为空,当不为空时,不在创建View对象,之间将View指向convertView对象的地址,当为空时,采取和1一样的操作,即将布局文件转化为View对象。

     1 //方式2:利用缓存的convertView对象,不用每次都重新创建View对象,减少了内存空间的分配
     2     @Override
     3     public View getView(int position, View convertView, ViewGroup parent) {
     4         View view = null;
     5 
     6         if(convertView!=null)
     7             view = convertView;
     8         else{
     9             // 将布局文件转化为View对象,通过View对象获取需要设置数据的UI组件对象(两种方法)
    10             // view =LayoutInflater.from(context).inflate(R.layout.item_layout,null);
    11             view = LayoutInflater.from(context).inflate(R.layout.item_layout,
    12                     parent, false);
    13         }
    14         
    15         ImageView image = (ImageView) view.findViewById(R.id.image);
    16         TextView title = (TextView) view.findViewById(R.id.title);
    17         TextView content = (TextView) view.findViewById(R.id.content);
    18 
    19         // 获取该position数据项要显示的数据
    20         Map<String, Object> map = (Map<String, Object>) getItem(position);
    21 
    22         // 设置数据
    23         image.setImageResource((Integer) map.get("image"));
    24         title.setText(map.get("title").toString());
    25         content.setText(map.get("content").toString());
    26 
    27         // 返回第position项的数据项视图
    28         return view;
    29     }

      3.文艺式:在2的基础上进行优化,首先创建一个内部类,然后利用new View.setTag(Object object)和new View.getTag()方法,减少findViewById(int)的次数,当数据巨大时,可以发挥显著的效果。

     1 //方式三:在方式2的基础上,利用一个内部类,同时调用view.setTag(Object object)和view.getTag()方法
     2     //减少了findViewById(int)的次数
     3     @Override
     4     public View getView(int position, View convertView, ViewGroup parent) {
     5         View view = null;
     6 
     7         if(convertView!=null)
     8             view = convertView;
     9         else{
    10             // 将布局文件转化为View对象,通过View对象获取需要设置数据的UI组件对象(两种方法)
    11             // view =LayoutInflater.from(context).inflate(R.layout.item_layout,null);
    12             view = LayoutInflater.from(context).inflate(R.layout.item_layout,
    13                     parent, false);
    14             ViewHolder holder = new ViewHolder();
    15             holder.image = (ImageView) view.findViewById(R.id.image);
    16             holder.title = (TextView) view.findViewById(R.id.title);
    17             holder.content = (TextView) view.findViewById(R.id.content);
    18             view.setTag(holder);
    19         }
    20         
    21         ViewHolder viewHolder = (ViewHolder) view.getTag();
    22 
    23         // 获取该position数据项要显示的数据
    24         Map<String, Object> map = (Map<String, Object>) getItem(position);
    25 
    26         // 设置数据
    27         viewHolder.image.setImageResource((Integer) map.get("image"));
    28         viewHolder.title.setText(map.get("title").toString());
    29         viewHolder.content.setText(map.get("content").toString());
    30 
    31         // 返回第position项的数据项视图
    32         return view;
    33     }
    34     class ViewHolder{
    35         ImageView image;
    36         TextView title;
    37         TextView content;
    38     }

    注意:

      1.内部类ViewHolder是一个自定义类,它的类名是自定义的,我们可以取不同的名字,而不一定非要为ViewHolder。

      2.参数列表中的参数View convertView,它缓存了使用过的视图,例如当AdapterView是ListView时,上滑动ListView,顶部的数据项View视图会不见,这时就缓存为convertView,

    上滑动多次,这时可能有多个convertView对象

      3.new View().setTag(Object object)和new View.getTag()方法,可以看作是当封装实体类时的setXXX()和getXXX()方法类似,便于理解和记忆。

    扩展:

      可以在一个方法中创建BaseAdapter的匿名内部类,也可以将自定义继承了BaseAdapter的类作为某个类的内部类,也可以如上单独定义一个外部类继承BaseAdapter,它们根据情景的不同可以灵活的使用。例如将自定义继承了BaseAdapter的类作为某个类的内部类,如果这个外部类中存在数据源,那么就可以直接访问外部类的数据源,就不需要像上面的例子样传递上下文对象和数据源了,有时候方便多了。

      示例:

      需求:MainActivity界面利用ListView显示10条数据,自定义适配器BaseAdapter,采用上述三种重写getView方法。

      MainActivity源码:

     1 package com.my.day21_my_listview3;
     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.my.day21_my_listview3.adapter.MyAdapter;
     9 
    10 import android.os.Bundle;
    11 import android.widget.ListView;
    12 import android.app.Activity;
    13 
    14 public class MainActivity extends Activity {
    15     private ListView listView;
    16     private MyAdapter adapter;
    17     private List<Map<String, Object>> data;
    18     
    19     @Override
    20     protected void onCreate(Bundle savedInstanceState) {
    21         super.onCreate(savedInstanceState);
    22         setContentView(R.layout.activity_main);
    23         
    24         //获取ListView组件对象
    25         listView = (ListView) findViewById(R.id.listView);
    26         
    27         //初始化数据源
    28         data = new ArrayList<Map<String,Object>>();
    29         for(int i=1;i<=10;i++){
    30             Map<String, Object> map = new HashMap<String, Object>();
    31             map.put("image", R.drawable.ic_launcher);
    32             map.put("title", "这是第"+i+"个数据项的标题");
    33             map.put("content", "这是第"+i+"个数据项的内容");
    34             data.add(map);
    35         }
    36         
    37         //创建适配器对象
    38         adapter = new MyAdapter(this,data);
    39         
    40         //绑定适配器
    41         listView.setAdapter(adapter);
    42     }
    43 }
    View Code

      MyAdapter源码:

      1 package com.my.day21_my_listview3.adapter;
      2 
      3 import java.util.List;
      4 import java.util.Map;
      5 
      6 import com.my.day21_my_listview3.R;
      7 
      8 import android.content.Context;
      9 import android.view.LayoutInflater;
     10 import android.view.View;
     11 import android.view.ViewGroup;
     12 import android.widget.BaseAdapter;
     13 import android.widget.ImageView;
     14 import android.widget.TextView;
     15 
     16 public class MyAdapter extends BaseAdapter {
     17     private Context context;
     18     private List<Map<String, Object>> data;
     19 
     20     public MyAdapter(Context context,List<Map<String, Object>> data){
     21         this.context = context;
     22         this.data = data;
     23     }
     24     
     25     @Override
     26     public int getCount() {
     27         int count = 0;
     28         if (data != null)
     29             count = data.size();
     30         return count;
     31     }
     32 
     33     @Override
     34     public Map<String, Object> getItem(int position) {
     35         return data.get(position);
     36     }
     37 
     38     @Override
     39     public long getItemId(int position) {
     40         return position;
     41     }
     42 
     43     /*@Override
     44     public View getView(int position, View convertView, ViewGroup parent) {
     45         View view = null;
     46 
     47         // 将布局文件转化为View对象,通过View对象获取需要设置数据的UI组件对象(两种方法)
     48         // view =LayoutInflater.from(context).inflate(R.layout.item_layout,null);
     49         view = LayoutInflater.from(context).inflate(R.layout.item_layout,
     50                 parent, false);
     51         ImageView image = (ImageView) view.findViewById(R.id.image);
     52         TextView title = (TextView) view.findViewById(R.id.title);
     53         TextView content = (TextView) view.findViewById(R.id.content);
     54 
     55         // 获取该position数据项要显示的数据
     56         Map<String, Object> map = (Map<String, Object>) getItem(position);
     57 
     58         // 设置数据
     59         image.setImageResource((Integer) map.get("image"));
     60         title.setText(map.get("title").toString());
     61         content.setText(map.get("content").toString());
     62 
     63         // 返回第position项的数据项视图
     64         return view;
     65     }*/
     66     
     67     /*//方式2:利用缓存的convertView对象,不用每次都重新创建View对象,减少了内存空间的分配
     68     @Override
     69     public View getView(int position, View convertView, ViewGroup parent) {
     70         View view = null;
     71 
     72         if(convertView!=null)
     73             view = convertView;
     74         else{
     75             // 将布局文件转化为View对象,通过View对象获取需要设置数据的UI组件对象(两种方法)
     76             // view =LayoutInflater.from(context).inflate(R.layout.item_layout,null);
     77             view = LayoutInflater.from(context).inflate(R.layout.item_layout,
     78                     parent, false);
     79         }
     80         
     81         ImageView image = (ImageView) view.findViewById(R.id.image);
     82         TextView title = (TextView) view.findViewById(R.id.title);
     83         TextView content = (TextView) view.findViewById(R.id.content);
     84 
     85         // 获取该position数据项要显示的数据
     86         Map<String, Object> map = (Map<String, Object>) getItem(position);
     87 
     88         // 设置数据
     89         image.setImageResource((Integer) map.get("image"));
     90         title.setText(map.get("title").toString());
     91         content.setText(map.get("content").toString());
     92 
     93         // 返回第position项的数据项视图
     94         return view;
     95     }*/
     96     
     97     //方式三:在方式2的基础上,利用一个内部类,同时调用view.setTag(Object object)和view.getTag()方法
     98     //减少了findViewById(int)的次数
     99     @Override
    100     public View getView(int position, View convertView, ViewGroup parent) {
    101         View view = null;
    102 
    103         if(convertView!=null)
    104             view = convertView;
    105         else{
    106             // 将布局文件转化为View对象,通过View对象获取需要设置数据的UI组件对象(两种方法)
    107             // view =LayoutInflater.from(context).inflate(R.layout.item_layout,null);
    108             view = LayoutInflater.from(context).inflate(R.layout.item_layout,
    109                     parent, false);
    110             ViewHolder holder = new ViewHolder();
    111             holder.image = (ImageView) view.findViewById(R.id.image);
    112             holder.title = (TextView) view.findViewById(R.id.title);
    113             holder.content = (TextView) view.findViewById(R.id.content);
    114             view.setTag(holder);
    115         }
    116         
    117         ViewHolder viewHolder = (ViewHolder) view.getTag();
    118 
    119         // 获取该position数据项要显示的数据
    120         Map<String, Object> map = (Map<String, Object>) getItem(position);
    121 
    122         // 设置数据
    123         viewHolder.image.setImageResource((Integer) map.get("image"));
    124         viewHolder.title.setText(map.get("title").toString());
    125         viewHolder.content.setText(map.get("content").toString());
    126 
    127         // 返回第position项的数据项视图
    128         return view;
    129     }
    130     class ViewHolder{
    131         ImageView image;
    132         TextView title;
    133         TextView content;
    134     }
    135 }
    View Code

      activity_main文件:

     1 <RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
     6     android:paddingLeft="@dimen/activity_horizontal_margin"
     7     android:paddingRight="@dimen/activity_horizontal_margin"
     8     android:paddingTop="@dimen/activity_vertical_margin"
     9     tools:context=".MainActivity" >
    10 
    11     <ListView
    12         android:id="@+id/listView"
    13         android:layout_width="match_parent"
    14         android:layout_height="match_parent" >
    15     </ListView>
    16 
    17 </RelativeLayout>
    View Code

      列表项布局item_layout文件:

     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     android:padding="10dp" >
     7 
     8     <ImageView
     9         android:id="@+id/image"
    10         android:layout_width="80dp"
    11         android:layout_height="80dp"
    12         android:scaleType="fitXY" />
    13 
    14     <LinearLayout
    15         android:layout_width="match_parent"
    16         android:layout_height="80dp"
    17         android:orientation="vertical" >
    18 
    19         <TextView
    20             android:id="@+id/title"
    21             android:layout_width="match_parent"
    22             android:layout_height="wrap_content"
    23             android:gravity="center"
    24             android:textSize="20sp"
    25             android:textStyle="bold" />
    26 
    27         <TextView
    28             android:id="@+id/content"
    29             android:layout_width="match_parent"
    30             android:layout_height="0dp"
    31             android:layout_marginLeft="20dp"
    32             android:layout_weight="1"
    33             android:gravity="center_horizontal" >
    34         </TextView>
    35     </LinearLayout>
    36 
    37 </LinearLayout>
    View Code

      效果图:

      未完,待续。

  • 相关阅读:
    20个Flutter实例视频教程-第07节: 毛玻璃效果制作
    20个Flutter实例视频教程-第06节: 酷炫的路由动画-2
    20个Flutter实例视频教程-第05节: 酷炫的路由动画-1
    20个Flutter实例视频教程-第04节: 不规则底部工具栏制作-2
    20个Flutter实例视频教程-第03节: 不规则底部工具栏制作-1
    20个Flutter实例视频教程-第02节: 底部导航栏制作-2
    hdu5371Hotaru&#39;s problem manacher算法
    怎样解除内容审查程序的password
    SQLite -- 嵌入式关系型数据库
    PIC18F4520 + NRF24L01
  • 原文地址:https://www.cnblogs.com/enjoy-coding/p/4798915.html
Copyright © 2020-2023  润新知