超级封装BaseAdapter,让你省下千万行代码

  1. 首先打造超级Viewholder
package com.ljh.powerfulladapter.util;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

public class CommonViewHolder {
    private int mPosition;
    /*
     * 用于存储holder里面的各个view,此集合比map效率高,但key必须为Integer
     */
    private SparseArray<View> mViews;
    /**
     * 复用的view
     */
    private View convertView;

    private CommonViewHolder(Context context,int position, int layoutId, ViewGroup parent) {
        this.mPosition = position;
        mViews = new SparseArray<View>();
        convertView = LayoutInflater.from(context).inflate(layoutId, parent,false);
        convertView.setTag(this);
    }

    public static CommonViewHolder getInstance(Context context,int layoutId,int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            return new CommonViewHolder(context, position, layoutId, parent);
        } else {
            CommonViewHolder holder = (CommonViewHolder) convertView.getTag();
            holder.mPosition = position;
            return holder;
        }

    }

    /**
     * 通过resourceId获取item里面的view
     * @param resourceId 控件的id
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T extends View> T getView(int resourceId) {
        View view = mViews.get(resourceId);
        if (view == null) {
            view = convertView.findViewById(resourceId);
            mViews.put(resourceId, view);
        }
        return (T) view;
    }

    /**
     * 为textview类型填充内容
     * @param resourceId
     * @param text
     * @return CommonViewHolder
     */
    public CommonViewHolder setText(int resourceId,CharSequence text ) {
        ((TextView) getView(resourceId)).setText(text);
        return this;
    }
    public CommonViewHolder setText(int resourceId,int resid ) {
        ((TextView) getView(resourceId)).setText(resid);
        return this;
    }
    /**
     * 为ImageView设置Bitmap
     * @param resourceId
     * @param bm
     * @return
     */
    public CommonViewHolder setBitmap(int resourceId,Bitmap bm) {
        ((ImageView)getView(resourceId)).setImageBitmap(bm);
        return  this;
    }
    public CommonViewHolder setImageDrawable(int resourceId,Drawable drawable) {
        ((ImageView)getView(resourceId)).setImageDrawable(drawable);
        return  this;
    }
    public CommonViewHolder setImageResource(int resourceId,int resId) {
        ((ImageView)getView(resourceId)).setImageResource(resId);
        return  this;
    }


    public View getConvertView() {
        return convertView;
    }
    /**
     * 获取当前item的位置
     * @return
     */
    public int getPosition() {
        return mPosition;
    }
}
  1. 打造超级BaseAdapter
package com.ljh.powerfulladapter.util;

import java.util.List;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

import com.ljh.powerfulladapter.R;

public abstract class CommonBaseAdapter<T> extends BaseAdapter {
    private Context mContext;
    private List<T> mDatas;

    public CommonBaseAdapter(Context context,List<T> datas) {
        this.mContext = context;
        this.mDatas = datas;
    }

    @Override
    public int getCount() {
        return mDatas.size();
    }

    @Override
    public T getItem(int position) {
        return mDatas.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public  View getView(int position, View convertView, ViewGroup parent) {
        CommonViewHolder holder = CommonViewHolder.getInstance(mContext, R.layout.listview_item, position, convertView, parent);
        convert(holder,mDatas.get(position));
        return holder.getConvertView();
    }
    /**
     * 填充holder里面控件的数据
     * @param holder
     * @param bean 
     */
    public abstract void convert(CommonViewHolder holder,T bean);
}
  1. 使用范例
    这是MainActivity
public class MainActivity extends Activity {
    private ListView listView;
    private List<Bean> mDatas;
//    private MyAdapter adapter;
    private CommonAdapter commonAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initDatas();
        initView();
        regisetListener();
    }

    @SuppressWarnings("deprecation")
    private void initDatas() {
        mDatas = new ArrayList<Bean>();
        for (int i = 0 ; i < 20; i ++) {
            mDatas.add(new Bean("Android 新技术" + i, "android 新技术,可以让你走上人生高富贵道路,不信,就来学吧!", "1231212112" + i, new Date().toLocaleString()));
        }
    }

    private void initView() {
        listView = (ListView) findViewById(R.id.listview);

//      adapter = new MyAdapter(this, mDatas);
//      listView.setAdapter(adapter);

        commonAdapter = new CommonAdapter(this, mDatas);
        listView.setAdapter(commonAdapter);
    }

    private void regisetListener() {
        listView.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                Bean bean = mDatas.get(position);
                Toast.makeText(MainActivity.this, bean.getTitle(), Toast.LENGTH_SHORT).show();
            }
        });
    }
}

main.xml布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.ljh.powerfulladapter.MainActivity" >

    <ListView
        android:id="@+id/listview"
        android:dividerHeight="2dip"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </ListView>

</RelativeLayout>

CommonAdapter 源码:

public class CommonAdapter extends CommonBaseAdapter<Bean> {
    public CommonAdapter(Context context,List<Bean> datas) {
        super(context, datas);
    }

    @Override
    public void convert(CommonViewHolder holder,final Bean bean) {
        holder.setText(R.id.title, bean.getTitle())
        .setText(R.id.desc, bean.getDesc())
        .setText(R.id.time, bean.getTime())
        .setText(R.id.phone, bean.getPhone());

        holder.setImageResource(R.id.timeMake, R.drawable.time_mark);

        //这个当布局里面有checkbox的时候,复用问题的解决
        final CheckBox cb = holder.getView(R.id.checkbox);
        cb.setChecked(bean.isCheck());
        cb.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                bean.setCheck(cb.isChecked());
            }
        });

    }
}

listview_item.xml布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:descendantFocusability="blocksDescendants"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:singleLine="true"
        android:text="Android 新技术1"
        android:textColor="#000"
        android:textSize="18sp" />

    <LinearLayout
        android:id="@+id/llDesc"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/title"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="5dip"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/desc"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="7"
            android:maxLines="2"
            android:text="Android 新技术1"
            android:textSize="16sp" />

        <CheckBox
            android:id="@+id/checkbox"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />
    </LinearLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/llDesc" >

        <ImageView
            android:id="@+id/timeMake"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="5dip" />

        <TextView
            android:id="@+id/time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="5dip"
            android:layout_toRightOf="@id/timeMake"
            android:singleLine="true"
            android:text="2015-4-18"
            android:textSize="14sp" />

        <TextView
            android:id="@+id/phone"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="10dp"
            android:layout_marginTop="5dip"
            android:background="#00ff00"
            android:singleLine="true"
            android:text="10086"
            android:textSize="14sp" />
    </RelativeLayout>

</RelativeLayout>

这是用用的Bean实体:

public class Bean {
    private String title;
    private String desc;
    private String phone;
    private String time;

    //这个当布局里面有checkbox的时候,复用问题的解决
    private boolean isCheck;
    //略去get/set等...
}

以上信息参考慕课网的hyman老师的视频,在此谢谢。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
通过封装BaseAdapter和RecyclerView.Adapter得到的通用的,简易的Adapter。项目地址:https://github.com/tianzhijiexian/CommonAdapter 效果图:已解决的问题 提升item的独立性,完美支持item被多处复用 item会根据type来做自动复用 支持多种类型的item 一个item仅会调用一次setViews(),避免重复建立监听器 一个item仅会触发一次绑定视图的操作,提示效率 支持dataBinding和其他第三方注入框架 提供了getView()方法来简化findViewById 支持通过item的构造方法来传入Activity对象 支持通过item的构造方法来传入item中事件的回调 提供了getConvertedData(data, type)方法来对item传入的数据做转换,方便拆包和提升item的复用性 支持viewpager的正常加载模式和懒加载 支持快速将listview的适配器切换为recyclerView的适配器 viewpager的notifyDataSetChanged可以正常更新界面 支持recyclerView的添加头部和底部 支持适配器的数据自动绑定,只用操作数据便可,adapter会自动notify界面零、重要接口adapter的item必须实现此接口,接口源码如下:public interface AdapterItem<T> {     /**      * @return item布局文件的layoutId      */     @LayoutRes     int getLayoutResId();     /**      * 初始化views      */     void bindViews(final View root);     /**      * 设置view的参数      */     void setViews();     /**      * 根据数据来设置item的内部views      *      * @param model    数据list内部的model      * @param position 当前adapter调用item的位置      */     void handleData(T model, int position); }例子:public class TextItem implements AdapterItem<DemoModel> {     @Override     public int getLayoutResId() {         return R.layout.demo_item_text;     }     TextView textView;     @Override     public void bindViews(View root) {         textView = (TextView) root.findViewById(R.id.textView);     }     @Override     public void setViews() { }     @Override     public void handleData(DemoModel model, int position) {         textView.setText(model.content);     } }一、ListView GridView的通用适配器——CommonAdapter只需继承CommonAdapter便可实现适配器:listView.setAdapter(new CommonAdapter<DemoModel>(data, 1) {     public AdapterItem<DemoModel> createItem(Object type) {         return new TextItem();     } });二、RecyclerView的通用适配器——CommonRcvAdapter通过继承CommonRcvAdapter来实现适配器:mAdapter = new CommonRcvAdapter<DemoModel>(data) {  public AdapterItem createItem(Object type) {         return new TextItem();   } };三、ViewPager的通用适配器——CommonPagerAdapter通过继承CommonPagerAdapter来实现适配器:viewPager.setAdapter(new CommonPagerAdapter<DemoModel>() {     public AdapterItem createItem(Object type) {         return new TextItem();     } });设计思路1. Adapter如果用adapter常规写法,你会发现代码量很大,可读性低。如果adapter中有多个类型的Item,我们还得在getView()中写很多if-else语句,很乱。 而现在我让adapter的代码量减少到一个8的内部类,如果你需要更换item只需要动一代码,真正实现了可插拔化。最关键的是item现在作为了一个独立的对象,可以方便的进复用。2. AdapterItem和原来方式最为不同的一点就是我把adapter的item作为了一个实体,这种方式借鉴了RecyclerView中ViewHolder的设计。把item作为实体的好处有很多,比如复用啊,封装啊,其余的就不细说了。3. 分层在使用过程中,我发现如果adapter放在view层,那就会影响到view层的独立性。此外adapter中经常有很多数据处理的操作,比如通过type选择item,数据的拆包、转换等操作。于是我还是推荐把adapter放在mvp的p层,或者是mvvm的m层。通过在实际的项目中使用来看,放在m或p层的效果较好,view的复用也比较好做。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值