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

下面先上一个例子,是使用ViewHolder进行显示效率优化过的工程:

package com.test.listviewsimpleadapter; 
 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
 
import android.app.AlertDialog; 
import android.app.ListActivity; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.BaseAdapter; 
import android.widget.Button; 
import android.widget.ImageView; 
import android.widget.ListView; 
import android.widget.TextView; 
 
/* listView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到listView的长
 * 度(这也是为什么在开始的第一张图特别的标出列表长度),然后根据这个长度,调用getView()逐
 * 一绘制每一行。如果你的getCount()返回值是0的话,列表将不显示同样return 1,就只显示一行。
 * 系统显示列表时,首先实例化一个适配器(这里将实例化自定义的适配器)。当手动完成适配时,必
 * 须手动映射数据,这需要重写getView()方法。系统在绘制列表的每一行的时候将调用此方法。
 * getView()有三个参数,position表示将显示的是第几行,covertView是从布局文件中inflate来的
 * 布局。我们用LayoutInflater的方法将定义好的main.xml文件提取成View实例用来显示。然后
 * 将xml文件中的各个组件实例化(简单的findViewById()方法)。这样便可以将数据对应到各个组件
 * 上了。但是按钮为了响应点击事件,需要为它添加点击监听器,这样就能捕获点击事件。至此一个自定
 * 义的listView就完成了,现在让我们回过头从新审视这个过程。系统要绘制ListView了,他首先获得
 * 要绘制的这个列表的长度,然后开始绘制第一行,怎么绘制呢?调用getView()函数。在这个函数里面
 * 首先获得一个View(实际上是一个ViewGroup),然后再实例并设置各个组件,显示之。好了,绘制完
 * 这一行了。那 再绘制下一行,直到绘完为止。在实际的运行过程中会发现listView的每一行没有焦点
 * 了,这是因为Button抢夺了listView的焦点,只要布局文件中将Button设置为没有焦点就OK了*/ 
 
public class MyListView4 extends ListActivity { 
 
    private List<Map<String, Object>> mData; 
 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        mData = getData(); 
        MyAdapter adapter = new MyAdapter(this); 
        setListAdapter(adapter); 
    } 
 
    private List<Map<String, Object>> getData() { 
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); 
 
        Map<String, Object> map = new HashMap<String, Object>(); 
        map.put("title", "G1"); 
        map.put("info", "google 1"); 
        map.put("img", R.drawable.i1); 
        list.add(map); 
 
        map = new HashMap<String, Object>(); 
        map.put("title", "G2"); 
        map.put("info", "google 2"); 
        map.put("img", R.drawable.i2); 
        list.add(map); 
 
        map = new HashMap<String, Object>(); 
        map.put("title", "G3"); 
        map.put("info", "google 3"); 
        map.put("img", R.drawable.i3); 
        list.add(map); 
 
        return list; 
    } 
 
    // ListView 中某项被选中后的逻辑  
    @Override 
    protected void onListItemClick(ListView l, View v, int position, long id) { 
        Log.v("MyListView4-click", (String) mData.get(position).get("title")); 
    } 
 
    /**
     * listview中点击按键弹出对话框
     */ 
    public void showInfo() { 
        new AlertDialog.Builder(this).setTitle("我的listview") 
                .setMessage("介绍...") 
                .setPositiveButton("确定", new DialogInterface.OnClickListener() { 
                    @Override 
                    public void onClick(DialogInterface dialog, int which) { 
                    } 
                }).show(); 
    } 
 
    public final class ViewHolder { 
        public ImageView img; 
        public TextView title; 
        public TextView info; 
        public Button viewBtn; 
    } 
 
    public class MyAdapter extends BaseAdapter { 
 
        private LayoutInflater mInflater; 
 
        public MyAdapter(Context context) { 
            this.mInflater = LayoutInflater.from(context); 
        } 
 
        @Override 
        public int getCount() { 
            // TODO Auto-generated method stub  
            return mData.size(); 
        } 
 
        @Override 
        public Object getItem(int arg0) { 
            // TODO Auto-generated method stub  
            return null; 
        } 
 
        @Override 
        public long getItemId(int arg0) { 
            // TODO Auto-generated method stub  
            return 0; 
        } 
 
        @Override 
        public View getView(int position, View convertView, ViewGroup parent) { 
            // 显示优化(只要之前显示过的就可以不再再次从布局文件读取,直接从缓存中读取——ViewHolder的作用)  
            // 其实是setTag和getTag中Tag的作用  
            ViewHolder holder = null; 
            if (convertView == null) {// 如果是第一次显示该页面(要记得保存到viewholder中供下次直接从缓存中调用)  
 
                holder = new ViewHolder(); 
 
                convertView = mInflater.inflate(R.layout.main, null); 
                // 以下为保存这一屏的内容,供下次回到这一屏的时候直接refresh,而不用重读布局文件  
                holder.img = (ImageView) convertView.findViewById(R.id.img); 
                holder.title = (TextView) convertView.findViewById(R.id.title); 
                holder.info = (TextView) convertView.findViewById(R.id.info); 
                holder.viewBtn = (Button) convertView 
                        .findViewById(R.id.view_btn); 
                convertView.setTag(holder); 
 
            } else {// 如果之前已经显示过该页面,则用viewholder中的缓存直接刷屏  
 
                holder = (ViewHolder) convertView.getTag(); 
            } 
 
            holder.img.setBackgroundResource((Integer) mData.get(position).get( 
                    "img")); 
            holder.title.setText((String) mData.get(position).get("title")); 
            holder.info.setText((String) mData.get(position).get("info")); 
 
            holder.viewBtn.setOnClickListener(new View.OnClickListener() { 
 
                @Override 
                public void onClick(View v) { 
                    showInfo(); 
                } 
            }); 
            return convertView; 
        } 
    } 

package com.test.listviewsimpleadapter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

/* listView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到listView的长
 * 度(这也是为什么在开始的第一张图特别的标出列表长度),然后根据这个长度,调用getView()逐
 * 一绘制每一行。如果你的getCount()返回值是0的话,列表将不显示同样return 1,就只显示一行。
 * 系统显示列表时,首先实例化一个适配器(这里将实例化自定义的适配器)。当手动完成适配时,必
 * 须手动映射数据,这需要重写getView()方法。系统在绘制列表的每一行的时候将调用此方法。
 * getView()有三个参数,position表示将显示的是第几行,covertView是从布局文件中inflate来的
 * 布局。我们用LayoutInflater的方法将定义好的main.xml文件提取成View实例用来显示。然后
 * 将xml文件中的各个组件实例化(简单的findViewById()方法)。这样便可以将数据对应到各个组件
 * 上了。但是按钮为了响应点击事件,需要为它添加点击监听器,这样就能捕获点击事件。至此一个自定
 * 义的listView就完成了,现在让我们回过头从新审视这个过程。系统要绘制ListView了,他首先获得
 * 要绘制的这个列表的长度,然后开始绘制第一行,怎么绘制呢?调用getView()函数。在这个函数里面
 * 首先获得一个View(实际上是一个ViewGroup),然后再实例并设置各个组件,显示之。好了,绘制完
 * 这一行了。那 再绘制下一行,直到绘完为止。在实际的运行过程中会发现listView的每一行没有焦点
 * 了,这是因为Button抢夺了listView的焦点,只要布局文件中将Button设置为没有焦点就OK了*/

public class MyListView4 extends ListActivity {

private List<Map<String, Object>> mData;

@Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  mData = getData();
  MyAdapter adapter = new MyAdapter(this);
  setListAdapter(adapter);
 }

private List<Map<String, Object>> getData() {
  List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

Map<String, Object> map = new HashMap<String, Object>();
  map.put("title", "G1");
  map.put("info", "google 1");
  map.put("img", R.drawable.i1);
  list.add(map);

map = new HashMap<String, Object>();
  map.put("title", "G2");
  map.put("info", "google 2");
  map.put("img", R.drawable.i2);
  list.add(map);

map = new HashMap<String, Object>();
  map.put("title", "G3");
  map.put("info", "google 3");
  map.put("img", R.drawable.i3);
  list.add(map);

return list;
 }

// ListView 中某项被选中后的逻辑
 @Override
 protected void onListItemClick(ListView l, View v, int position, long id) {
  Log.v("MyListView4-click", (String) mData.get(position).get("title"));
 }

/**
  * listview中点击按键弹出对话框
  */
 public void showInfo() {
  new AlertDialog.Builder(this).setTitle("我的listview")
    .setMessage("介绍...")
    .setPositiveButton("确定", new DialogInterface.OnClickListener() {
     @Override
     public void onClick(DialogInterface dialog, int which) {
     }
    }).show();
 }

public final class ViewHolder {
  public ImageView img;
  public TextView title;
  public TextView info;
  public Button viewBtn;
 }

public class MyAdapter extends BaseAdapter {

private LayoutInflater mInflater;

public MyAdapter(Context context) {
   this.mInflater = LayoutInflater.from(context);
  }

@Override
  public int getCount() {
   // TODO Auto-generated method stub
   return mData.size();
  }

@Override
  public Object getItem(int arg0) {
   // TODO Auto-generated method stub
   return null;
  }

@Override
  public long getItemId(int arg0) {
   // TODO Auto-generated method stub
   return 0;
  }

@Override
  public View getView(int position, View convertView, ViewGroup parent) {
   // 显示优化(只要之前显示过的就可以不再再次从布局文件读取,直接从缓存中读取——ViewHolder的作用)
   // 其实是setTag和getTag中Tag的作用
   ViewHolder holder = null;
   if (convertView == null) {// 如果是第一次显示该页面(要记得保存到viewholder中供下次直接从缓存中调用)

holder = new ViewHolder();

convertView = mInflater.inflate(R.layout.main, null);
    // 以下为保存这一屏的内容,供下次回到这一屏的时候直接refresh,而不用重读布局文件
    holder.img = (ImageView) convertView.findViewById(R.id.img);
    holder.title = (TextView) convertView.findViewById(R.id.title);
    holder.info = (TextView) convertView.findViewById(R.id.info);
    holder.viewBtn = (Button) convertView
      .findViewById(R.id.view_btn);
    convertView.setTag(holder);

} else {// 如果之前已经显示过该页面,则用viewholder中的缓存直接刷屏

holder = (ViewHolder) convertView.getTag();
   }

holder.img.setBackgroundResource((Integer) mData.get(position).get(
     "img"));
   holder.title.setText((String) mData.get(position).get("title"));
   holder.info.setText((String) mData.get(position).get("info"));

holder.viewBtn.setOnClickListener(new View.OnClickListener() {

@Override
    public void onClick(View v) {
     showInfo();
    }
   });
   return convertView;
  }
 }
}

下面是将自定义的Adapter的构造方法定义为与系统的Adapter一致的工程,这样大家在实例化自定义的Adapter时可以按照实例化系统的Adapter的参数安排来进行哟~

package com.test.listviewsimpleadapter;

import java.util.List;
import java.util.Map;
import android.app.AlertDialog;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.CompoundButton.OnCheckedChangeListener;
/**
 * @author Himi
 *
 */
public class MySimpleAdapter extends BaseAdapter {
 private LayoutInflater mInflater;
 private List<Map<String, Object>> list;
 private int layoutID;
 private String flag[];
 private int ItemIDs[];
 public MySimpleAdapter(Context context, List<Map<String, Object>> list,
   int layoutID, String flag[], int ItemIDs[]) {
  Log.i("TAG","构造方法");
  this.mInflater = LayoutInflater.from(context);
  this.list = list;
  this.layoutID = layoutID;
  this.flag = flag;
  this.ItemIDs = ItemIDs;
 }
 @Override
 public int getCount() {
  // TODO Auto-generated method stub
  return list.size();
 }
 @Override
 public Object getItem(int arg0) {
  // TODO Auto-generated method stub
  return 0;
 }
 @Override
 public long getItemId(int arg0) {
  // TODO Auto-generated method stub
  return 0;
 }
 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
  convertView = mInflater.inflate(layoutID, null);
  for (int i = 0; i < flag.length; i++) {//备注1
   if (convertView.findViewById(ItemIDs[i]) instanceof ImageView) {
    ImageView iv = (ImageView) convertView.findViewById(ItemIDs[i]);
    iv.setBackgroundResource((Integer) list.get(position).get(
      flag[i]));
   } else if (convertView.findViewById(ItemIDs[i]) instanceof TextView) {
    TextView tv = (TextView) convertView.findViewById(ItemIDs[i]);
    tv.setText((String) list.get(position).get(flag[i]));
   }else{
    //...备注2
    Log.i("TAG","else");
   }
  }
  addListener(convertView);
  return convertView;
 }
/**
 * 童鞋们只需要将需要设置监听事件的组件写在下面这方法里就可以啦!
 * 别的不需要修改!
 * 备注3
 */
 public void addListener(View convertView) {
  ((Button)convertView.findViewById(R.id.btn)).setOnClickListener(
    new View.OnClickListener() {
     @Override
     public void onClick(View v) {
      new AlertDialog.Builder(LvSimpleAdapter.ma)
      .setTitle("自定义通用SimpleAdapter")
      .setMessage("按钮成功触发监听事件!")
      .show();
      Log.i("TAG","Button");
     }
    });
  ((CheckBox)convertView.findViewById(R.id.cb)).
  setOnCheckedChangeListener(new OnCheckedChangeListener() {
   @Override
   public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    new AlertDialog.Builder(LvSimpleAdapter.ma)
    .setTitle("自定义通用SimpleAdapter")
    .setMessage("CheckBox成功触发状态改变监听事件!")
    .show();
    Log.i("TAG","CheckBox");
   }
  });
 }
}

以上代码的注释都比较详细,而且前面的Blog中也对Adapter进行过讲解,这边就不再说一遍啦~

其中第二段代码中没有使用ViewHolder对显示效率进行优化,大家可以参考第一段稍稍改动一下就OK了哈~

Android中的自定义Adapter(继承自BaseAdapter)——与系统Adapter的调用方法一致——含ViewHolder显示效率的优化(转)的更多相关文章

  1. Android中制作自定义dialog对话框的实例

    http://www.jb51.net/article/83319.htm   这篇文章主要介绍了Android中制作自定义dialog对话框的实例分享,安卓自带的Dialog显然不够用,因而我们要继 ...

  2. Android中适用于ListView、GridView等组件的通用Adapter

    今天随便逛逛CSDN,看到主页上推荐了一篇文章Android 高速开发系列 打造万能的ListView GridView 适配器,刚好这两天写项目自己也封装了相似的CommonAdapter,曾经也在 ...

  3. Android 中使用自定义字体的方法

    1.Android系统默认支持三种字体,分别为:“sans”, “serif”, “monospace 2.在Android中可以引入其他字体 . <?xml version="1.0 ...

  4. Android中的自定义注解(反射实现-运行时注解)

    预备知识: Java注解基础 Java反射原理 Java动态代理 一.布局文件的注解 我们在Android开发的时候,总是会写到setContentView方法,为了避免每次都写重复的代码,我们需要使 ...

  5. Vue实例中封装api接口的思路 在页面中用async,await调用方法请求

    一般我们写小型的项目是用不到封装axios实例 但是当我们写大型项目时  接口有时候多到有上百个接口,那我们在请求一次调用一次接口,接口上好多都是重复的,这个时候我们就可以封装axios实例,既节省了 ...

  6. Android中的自定义视图控件

    简介 当现有控件不能满足需求时,就需要自定义控件. 自定义控件属性 自定义控件首先要继承自View,重写两个构造函数. 第一个是代码中使用的: public MyRect(Context contex ...

  7. Android中实现自定义View组件并使其能跟随鼠标移动

    场景 实现效果如下 注: 博客: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程序猿 获取编程相关电子书.教程推送与免费下载. 实现 新建An ...

  8. Android中使用自定义View实现下载进度的显示

    一般有下载功能的应用都会有这样一个场景,需要一个图标来标识不同的状态.之前在公司的项目中写过一个,今天抽空来整理一下. 一般下载都会有这么几种状态:未开始.等待.正在下载.下载结束,当然有时候会有下载 ...

  9. android中通过自定义xml实现你需要的shape效果 xml属性配置

    在Android开发过程中,经常需要改变控件的默认样式, 那么通常会使用多个图片来解决.不过这种方式可能需要多个图片,比如一个按钮,需要点击时的式样图片,默认的式样图片,然后在写一个selector的 ...

随机推荐

  1. 利用JFreeChart绘制股票K线图完整解决方案

    http://blog.sina.com.cn/s/blog_4ad042e50100q7d9.html 利用JFreeChart绘制股票K线图完整解决方案 (2011-04-30 13:27:17) ...

  2. ECOS-认证地址

    ECOS系统授权认证,需要和Shopex认证中心互联.当服务器DNS无效时.需要绑定host强行解析服务器强行解析以下vim /etc/hosts 122.144.135.142 service.sh ...

  3. how to increase an regular array length in java?

    Arrays in Java are of fixed size that is specified when they are declared. To increase the size of t ...

  4. 严格递增类的dp Codeforces Round #371 (Div. 1) C dp

    http://codeforces.com/contest/713 题目大意:给你一个长度为n的数组,每次有+1和-1操作,在该操作下把该数组变成严格递增所需要的最小修改值是多少 思路:遇到这类题型, ...

  5. XTEA加密算法

    XTEA加密算法 #include <stdint.h> /* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - ...

  6. Java中获取路径的方法_自我分析

    就目前的我来说最常用的两种获取路径的方法是  class.getRecource(filename) 和 class.getclassloader.getRecource(filename) 这两者的 ...

  7. LightOJ 1341 Aladdin and the Flying Carpet 算数基本定理

    题目大意:给出面积n,和最短边m,求能形成的矩形的个数(不能为正方形). 题目思路:根据算数基本定理有: 1.每个数n都能被分解为:n=p1^a1*p2^a2*^p3^a3……pn^an(p为素数); ...

  8. java数据结构之链表的实现

    这个链表的内部是使用双向链表来表示的,但是并未在主函数中进行使用 /** * 链表 * 2016/4/26 **/ class LinkList{ Node head = new Node(); No ...

  9. c# 去除文本的html标签

    public static string ContentReplace(string input) { input = Regex.Replace(input, @"<(.[^> ...

  10. UVALive 4031 Integer Transmission(贪心 + DP)

    分析:求出最大值和最小值比较简单,使用贪心法,求最小值的时候我们让所有的0尽可能的向后延迟就可以了,求最大值则相反. 关键在于求出可以组合出的数字个数. 这就是组合数学版的dp了,我们让dp[i][j ...