Android进阶学习-打造一个通用的Adapter

先来看看我们最普通的Adapter是怎样的吧.

代码:

package com.example.august.commonadapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.List;
/**
 * Created by August on 16/4/9.
 */
public class MyAdapter extends BaseAdapter {
    private List<String> mDatas;
    private Context mContext;
    public MyAdapter(List<String> mDatas, Context mContext) {
        this.mDatas = mDatas;
        this.mContext = mContext;
    }
    @Override
    public int getCount() {
        return mDatas.size();
    }
    @Override
    public Object getItem(int position) {
        return mDatas.get(position);
    }
    @Override
    public long getItemId(int position) {
        return 0;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {
            LayoutInflater inflater = LayoutInflater.from(mContext);
            convertView = inflater.inflate(R.layout.item_text, null);
            holder = new ViewHolder();
            holder.mTextView = (TextView) convertView.findViewById(R.id.mTextView);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.mTextView.setText(mDatas.get(position));
        return convertView;
    }
    class ViewHolder {
        TextView mTextView;
    }
}

每次写的Adapter都写得要死,一堆都是复用的代码,下面我们就开始封装一个自己的通用Adapter,把以后的代码量尽可能减少.

findView的时间,我们会用一个ViewHolderl来保存之前查找的view.以上的Adapter思路就是给Adapter传入一个经常调用的context参数还有适配的数据,其中构造器,getCount,getItem,getItemId,几乎是一样的.然后为了减少.其中我们找出每个Adapter可能不同的内容有哪些:

    1.mDatas的类型    这个简单,我们使用泛型来解决

    2.解析的Layout里面的View不确定,所以ViewHolder比较难搞

    其中第二个我们稍微比较麻烦一点,但是想想也挺简单的.想象ViewHolder就是一个容器,我们把View塞进去里面就好了.那我们就要用到容器了.好了知道用容器了,那么我们需要怎样去确定要使用哪个View呢?哈哈,也很简单,你会想到Map,key就是View的ID,value就是对应的View了.但我们这里推荐使用SparseArray容器,因为它的速度比常用的Map快多了,唯一确定就是键值只能是Integer型的,但是已经足够了...

下面是我们的ViewHolder代码,我们也需要像前面一样,把holder设置到对应的converview里面去.这样我们就可以从converview里面获取已经存在的holder了,详情看代码

public class ViewHolder {
    private SparseArray<View> mViews;
    private View mConvertview;
    public ViewHolder(View converview) {
        this.mConvertview = converview;
        mViews = new SparseArray<View>();
    }
    public static ViewHolder getHolder(Context context, View converview, int layoutID, ViewGroup parent) {
        ViewHolder holder = null;
        if (converview == null) {
            converview = LayoutInflater.from(context).inflate(layoutID, parent, false);
            holder = new ViewHolder(converview);
            converview.setTag(holder);
        } else {
            holder = (ViewHolder) converview.getTag();
        }
        return holder;
    }
}

    这样我们就可以使用getHolder方法来去新建或取回一个ViewHolder了,有了ViewHolder还不行,我们还要获取里面的View,这里我们使用泛型去写

  public <T extends View> T getView(int viewID) {
        T view = (T) mViews.get(viewID);
        if (view == null) {
            view = (T) mConvertview.findViewById(viewID);
            mViews.put(viewID, view);
        }
        return view;
    }

    这样以后我们就可以获取View并且作相应操作了

    下面开始编写我们GeneralParentAdapter了,因为是通用的,所以Adapter对应的Layout就需要以参数的形式传入,mDatas也需要时泛型的.

package com.example.august.commonadapter;
import android.content.Context;
import android.graphics.Bitmap;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
/**
 * Created by August on 16/4/9.
 */
public class GeneralParentAdapter<T> extends BaseAdapter {
    private List<T> mDatas;
    private Context mContext;
    private int layoutID;
    private ViewHolder holder;
    public GeneralParentAdapter(List<T> mDatas, Context mContext, int layoutID) {
        this.mDatas = mDatas;
        this.mContext = mContext;
        this.layoutID = layoutID;
    }
    @Override
    public int getCount() {
        return mDatas.size();
    }
    @Override
    public Object getItem(int position) {
        return mDatas.get(position);
    }
    @Override
    public long getItemId(int position) {
        return 0;
    }
}

嗯,这就是那堆让人讨厌的经常反反复复去写的代码

下面是Adapter的getView方法了,这里就要使用到ViewHolder了

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        holder = ViewHolder.getHolder(mContext, convertView, layoutID, parent);
        
        TextView mTextView = holder.getView(R.id.mTextView);
        mTextView.setText(mDatas.get(position));
        return holder.getConverview();
    }

然后我们发现,第一行和最后一行也是可以复用的,而且我们需要返回一个converView,那么我们就在ViewHolder添加一个方法吧

public View getConverview() {
        return this.mConvertview;
    }

继续,我们的Adapter就能用的,但是还不行,我们再把设置内容那里抽取出来,这才是每个Adapter真正的不同之处.现在我们把Adapter变成抽象类,并设置抽象方法setContent

  @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        holder = ViewHolder.getHolder(mContext, convertView, layoutID, parent);
        setContent(holder, mDatas, position);
        return holder.getConverview();
    }
    public abstract void setContent(ViewHolder holder, List<T> mDatas, int position);

最后我们就可以使用了

ItemBean.java

package com.example.august.commonadapter;
/**
 * Created by August on 16/4/9.
 */
public class ItemBean {
    public int imgID;
    public String text;
    public ItemBean(int imgID, String text) {
        this.imgID = imgID;
        this.text = text;
    }
}

item_text.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="horizontal">
    <ImageView
        android:id="@+id/mImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/mTextView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="center"
        android:textSize="18sp" />
</LinearLayout>

调用代码

        mListView = (ListView) findViewById(R.id.mListView);
        List<ItemBean> mDatas = new ArrayList<ItemBean>();
        for (int i = 'A'; i < 'Z'; i++) {
            ItemBean itemBean = new ItemBean(R.drawable.pic, String.valueOf((char) i));
            mDatas.add(itemBean);
        }
        GeneralParentAdapter<ItemBean> mAdapter = new GeneralParentAdapter<ItemBean>(mDatas, MainActivity.this, R.layout.item_text) {
            @Override
            public void setContent(ViewHolder holder, List<ItemBean> mDatas, int postion) {
                TextView mTextView = holder.getView(R.id.mTextView);
                mTextView.setText("666");
                ImageView mImageView = holder.getView(R.id.mImageView);
                mImageView.setImageResource(R.drawable.pic);
            }
        };
        mListView.setAdapter(mAdapter);

可以看到我们需要写的代码从一堆变成了短小精悍的几行,但还不够,我们还得上天呢 哈哈.我们再给ViewHolder设置一些通用的方法,无非是什么setText,setBitmap之类的,于是VIewHolder有了...

  public void setText(int viewID, String text) {
        View childView = getView(viewID);
        if (childView instanceof TextView) {
            ((TextView) childView).setText(text);
        }
    }
    public void setBitmap(int viewID, Bitmap bitmap) {
        View childView = getView(viewID);
        if (childView instanceof ImageView) {
            ((ImageView) childView).setImageBitmap(bitmap);
        }
    }

最后我们继续精简

        GeneralParentAdapter<ItemBean> mAdapter = new GeneralParentAdapter<ItemBean>(mDatas, MainActivity.this, R.layout.item_text) {
            @Override
            public void setContent(ViewHolder holder, List<ItemBean> mDatas, int postion) {
                holder.setText(R.id.mTextView, mDatas.get(postion).text);
                holder.setBitmap(R.id.mImageView, BitmapFactory.decodeResource(getResources(), R.drawable.pic));
            }
        };

最后变成了两行代码,咱们就呵呵了...大家还可以根据自己需要去封装更多的方法.

ViewHolder代码:

package com.example.august.commonadapter;
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;
/**
 * Created by August on 16/4/9.
 */
public class ViewHolder {
    private SparseArray<View> mViews;
    private View mConvertview;
    public ViewHolder(View converview) {
        this.mConvertview = converview;
        mViews = new SparseArray<View>();
    }
    public static ViewHolder getHolder(Context context, View converview, int layoutID, ViewGroup parent) {
        ViewHolder holder = null;
        if (converview == null) {
            converview = LayoutInflater.from(context).inflate(layoutID, parent, false);
            holder = new ViewHolder(converview);
            converview.setTag(holder);
        } else {
            holder = (ViewHolder) converview.getTag();
        }
        return holder;
    }
    public <T extends View> T getView(int viewID) {
        T view = (T) mViews.get(viewID);
        if (view == null) {
            view = (T) mConvertview.findViewById(viewID);
            mViews.put(viewID, view);
        }
        return view;
    }
    public View getConverview() {
        return this.mConvertview;
    }
    public void setText(int viewID, String text) {
        View childView = getView(viewID);
        if (childView instanceof TextView) {
            ((TextView) childView).setText(text);
        }
    }
    public void setBitmap(int viewID, Bitmap bitmap) {
        View childView = getView(viewID);
        if (childView instanceof ImageView) {
            ((ImageView) childView).setImageBitmap(bitmap);
        }
    }
}


 

GeneralParentAdapter代码:

package com.example.august.commonadapter;
import android.content.Context;
import android.graphics.Bitmap;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
/**
 * Created by August on 16/4/9.
 */
public abstract class GeneralParentAdapter<T> extends BaseAdapter {
    private List<T> mDatas;
    private Context mContext;
    private int layoutID;
    private ViewHolder holder;
    public GeneralParentAdapter(List<T> mDatas, Context mContext, int layoutID) {
        this.mDatas = mDatas;
        this.mContext = mContext;
        this.layoutID = layoutID;
    }
    @Override
    public int getCount() {
        return mDatas.size();
    }
    @Override
    public Object getItem(int position) {
        return mDatas.get(position);
    }
    @Override
    public long getItemId(int position) {
        return 0;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        holder = ViewHolder.getHolder(mContext, convertView, layoutID, parent);
        setContent(holder, mDatas, position);
        return holder.getConverview();
    }
    public abstract void setContent(ViewHolder holder, List<T> mDatas, int position);
}


 

转载于:https://my.oschina.net/august1996/blog/655922

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值