zoukankan      html  css  js  c++  java
  • android打造万能适配器

    1、概述

    相信做Android开发的写得最多的就是ListView,GridView的适配器吧,记得以前开发一同事开发项目,一个项目下来基本就一直在写ListView的Adapter都快吐了~~~对于Adapter一般都继承BaseAdapter复写几个方法,getView里面使用ViewHolder模式,其实大部分的代码基本都是类似的。

    本篇博客为快速开发系列的第一篇,将一步一步带您封装出一个通用的Adapter

    2、创建ViewHolder

    首先分析下ViewHolder的作用,通过convertView.setTag与convertView进行绑定,然后当convertView复用时,直接从与之对于的ViewHolder(getTag)中拿到convertView布局中的控件,省去了findViewById的时间~

    也就是说,实际上们每个convertView会绑定一个ViewHolder对象,这个viewHolder主要用于帮convertView存储布局中的控件。

    那么我们只要写出一个通用的ViewHolder,然后对于任意的convertView,提供一个对象让其setTag即可;

    既然是通用,那么我们这个ViewHolder就不可能含有各种控件的成员变量了,因为每个Item的布局是不同的,最好的方式是什么呢?

    提供一个容器,专门存每个Item布局中的所有控件,而且还要能够查找出来;既然需要查找,那么ListView肯定是不行了,需要一个键值对进行保存,键为控件的Id,值为控件的引用,相信大家立刻就能想到Map;但是我们不用Map,因为有更好的替代类,就是我们android提供的SparseArray这个类,和Map类似,但是比Map效率,不过键只能为Integer.

    import android.content.Context;
    import android.graphics.Bitmap;
    import android.util.SparseArray;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    /**
     *构造一个通用的viewholder类
     *
     */
    public class ViewHolder {
    	private SparseArray<View> mViews;
    	private int mPosition;
    	private View mConvertView;
    	//layoutId即我们要引入的item布局文件的id
    	public ViewHolder(Context context, ViewGroup parent, int layoutId, int position)
    	{
    		this.mPosition = position;
    		this.mViews = new SparseArray<View>();
    		mConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false);//引入我们的item布局文件
    		mConvertView.setTag(this);
    	}
    	//ViewHolder并不是每次都需要实例化,当convertview不为空时我们就不需要再实例化ViewHolder,因此我们增加一个入口方法
    	//来判断是否需要对ViewHolder实例化
    	public static ViewHolder get(Context context, View convertView, ViewGroup parent, int layoutId, int position)
    	{
    		if (convertView == null) {
    			return new ViewHolder(context, parent, layoutId, position);//返回一个实例化对象
    		}
    		else {
    			ViewHolder holder = (ViewHolder) convertView.getTag();
    			holder.mPosition = position;
    			return holder;
    		}
    	}
    	
    	/**
    	 * ͨ通过viewId获取控件,此方法返回的是View的一个子类
    	 */
    	public <T extends View> T getView(int viewId)
    	{
    		View view = mViews.get(viewId);
    		if (view == null) {
    			//如果mViews没有相应的控件,我们就从convertView中找到这个控件,并将此控件和其id存放在mViews中
    			view = mConvertView.findViewById(viewId);
    			mViews.put(viewId, view);
    		}
    		return (T) view;
    	}
    	//mConvertView的get方法
    	public View getConvertView() {
    		return mConvertView;
    	}	
    	/**
    	 * 找到我们定义的TextView控件,并给控件赋值
    	 */
    	public ViewHolder setText(int viewId, String text)
    	{
    		TextView tv = getView(viewId);
    		tv.setText(text);
    		return this;
    	}
    	
    	/**
    	 * 如果item中有ImageView控件的话,我们就可以用此方法给控件设置图片资源
    	 */
    	public ViewHolder setImageResource(int viewId, int resId)
    	{
    		ImageView imageView = getView(viewId);
    		imageView.setImageResource(resId);
    		return this;
    	}
    	public ViewHolder setImageBitmap(int viewId, Bitmap bitmap)
    	{
    		ImageView imageView = getView(viewId);
    		imageView.setImageBitmap(bitmap);
    		return this;
    	}
    	//我们还可以添加其他的更多的方法。。。。。。。。。。。
    
    }
    分别可以通过setText()、setImageResource()、setImageBitmap() 来设置文字信息,图片

    只看getView,其他方法都一样;首先调用ViewHolder的get方法,如果convertView为null,new一个ViewHolder实例,通过使用mInflater.inflate加载布局,然后new一个SparseArray用于存储View,最后setTag(this);如果存在那么直接getTag,最后通过getView(id)获取控件,如果存在则直接返回,否则调用findViewById,返回存储,返回。

    3、创建Adapter基类

    import java.util.List;
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.TextView;
    
    /**
     * 编写通用的Adapter,指定泛型,以便适应不同的Java bean
     * @param <T>
     */
    public abstract class CommonAdapter<T> extends BaseAdapter {
    	//这些属性都是每个适配器中都能用到的,访问控制符设置为protected,以便继承的子类都能访问
    	protected LayoutInflater mInflater;
    	protected List<T> mDatas;//数据源
    	protected Context mContext;
    	protected int layoutId;//item布局文件
    	
    	public CommonAdapter(Context context, List<T> mDatas, int layoutId) {
    		this.mContext = context;
    		this.mDatas = mDatas;
    		mInflater = LayoutInflater.from(context);
    		this.layoutId = layoutId;
    	}
    
    	@Override
    	public int getCount() {		
    		return mDatas.size();
    	}
    
    	@Override
    	public T getItem(int position) {//这里的返回值类型是T,不是自动生成的Object
    		return mDatas.get(position);
    	}
    
    	@Override
    	public long getItemId(int position) {
    		return position;
    	}
    	
    	@Override
    	public View getView(int position, View convertView, ViewGroup parent)
    	{
    		//初始化ViewHolder,加载我们的item布局文件
    		ViewHolder holder = ViewHolder.get(mContext, convertView, parent, layoutId, position);
    		convert(holder, getItem(position));//getItem(position)的类型就是T,这句话在子类中的具体实现就是给具体的控件初始化
    		//并赋值,初始化赋值控件时需要viewHolder和具体的数据Java bean,在这里抽象出来就是类型T
    		return holder.getConvertView();//返回convertView
    	}
    	public abstract void convert(ViewHolder holder, T t);
    
    }





  • 相关阅读:
    RAID 0 软件实现(Windows 系统)
    keepalived 实现LVS负载均衡高可用集群(一)
    ISCSI服务端-客户端基础配置
    LVS负载分担(DR模式)基础搭建(一)
    LVS负载分担(NAT模式)基础搭建
    Chronyd同步时间(Server/Client)配置
    代码签名
    paillier加密算法原理详解
    pip安装了包但pycharm里找不到(pip如何安装到conda下)
    苹果系统iOS、macOS应用管理机制
  • 原文地址:https://www.cnblogs.com/vegetate/p/9997303.html
Copyright © 2011-2022 走看看