Android万能适配器CommonAdapter的源码分析

来源:互联网 发布:美国劳工部公布的数据 编辑:程序博客网 时间:2024/04/30 02:40

1.ViewFinder的实现

package com.mycollege.util;import java.lang.ref.WeakReference;import android.content.Context;import android.util.Log;import android.util.SparseArray;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;/** * @{# ViewFinder.java Create on 2015-7-17 下午7:36:43 *  *     class desc:  view finder, 方便查找View。用户需要在使用时调用initContentView, * 将Context和布局id传进来,然后使用findViewById来获取需要的view * ,findViewById为泛型方法,返回的view则直接是你接收的类型,而不需要进行强制类型转换.比如, * 以前我们在Activity中找一个TextView一般是这样 : TextView textView = * (TextView)findViewById(viewId); 如果页面中的控件比较多,就会有很多的类型转换,而使用ViewFinder则免去了类型转换, * 示例如下 : TextView textView = ViewFinder.findViewById(viewId); *  *     <p> *     Copyright: Copyright(c) 2015 *     </p> * @Version 1.0 * Tel 15211164134  * Name 潘传爱 * @Author <a href="15211164134@163.com">Hyca</a> *  */public final class ViewFinder {    /**     *      */    public static boolean DEBUG = false;    /**     * 每项的View的sub view Map     */    private static SparseArray<WeakReference<View>> mViewMap = new SparseArray<WeakReference<View>>();    /**     * Root View的弱引用,     * 不会阻止View对象被释放。如果该mRootView没有被外部引用,那么在重新设置了rootView之后老的rootview会被释放.     */    private static WeakReference<View> mRootView;    /**     * 设置Content View     *      * @param contentView 页面的Content View     */    public static void initContentView(View contentView) {        if (contentView == null) {            throw new RuntimeException(                    "ViewFinder init failed, mContentView == null.");        }        //        mRootView = new WeakReference<View>(contentView);        // 每次清除缓存的view id        mViewMap.clear();    }    /**     * 初始化ViewFinder, 实际上是获取到该页面的ContentView.     *      * @param context     * @param layoutId     */    public static void initContentView(Context context, int layoutId) {        initContentView(context, null, layoutId);    }    /**     * @param context 上下文环境那个     * @param parent 父组件 ( ViewGroup )     * @param layoutId 布局id     */    public static void initContentView(Context context, ViewGroup parent, int layoutId) {        if (context == null || layoutId <= 0) {            throw new RuntimeException(                    "initContentView invalid params, context == null || layoutId == -1.");        }        // inflate the root view        View rootView = LayoutInflater.from(context).inflate(layoutId, parent, false);        //        initContentView(rootView);    }    /**     * 返回顶级视图     *      * @return     */    public static View getContentView() {        return mRootView.get();    }    /**     * @param viewId     * @return     */    @SuppressWarnings("unchecked")    public static <T extends View> T findViewById(int viewId) {        // 先从view map中查找,如果有的缓存的话直接使用,否则再从mContentView中找        View targetView = null;        // get from weak reference        WeakReference<View> viewWrf = mViewMap.get(viewId);        if (viewWrf != null) {            targetView = viewWrf.get();        }        if (targetView == null && mRootView != null && mRootView.get() != null) {            targetView = mRootView.get().findViewById(viewId);            mViewMap.put(viewId, new WeakReference<View>(targetView));        }        Log.d("", "### find view = " + targetView);        return targetView == null ? null : (T) targetView;    }    @SuppressWarnings("unchecked")    public static <T extends View> T findViewById(View rootView, int viewId) {        // 先从view map中查找,如果有的缓存的话直接使用,否则再从mContentView中找        View targetView = null;        // get from weak reference        if (rootView != null) {            targetView = rootView.findViewById(viewId);        }        Log.d("", "### find view = " + targetView);        return targetView == null ? null : (T) targetView;    }    /**     * 清理Views     */    public static void clear() {        if (mRootView != null) {            mRootView.clear();            mRootView = null;        }        if (mViewMap != null) {            mViewMap.clear();            mViewMap = null;        }    }}

2.CommonViewHolder的实现

package com.mycollege.util;import android.content.Context;import android.graphics.Bitmap;import android.view.LayoutInflater;import android.view.View;import android.view.View.OnClickListener;import android.view.View.OnTouchListener;import android.view.ViewGroup;import android.widget.CheckBox;import android.widget.ImageView;import android.widget.TextView;/** * @{# CommonViewHolder.java Create on 2015-7-17 下午7:35:59 *  *     class desc: 这是一个通用的ViewHolder, 将会装载AbsListView子类的item View, 并且将item *    view中的子视图进行缓存和索引,使得用户能够方便的获取这些子view, 减少了代码重复。 *     <p> *     Copyright: Copyright(c) 2015 *     </p> * @Version 1.0 * Tel 15211164134  * Name 潘传爱 * @Author <a href="15211164134@163.com">Hyca</a> *  */public class CommonViewHolder {    /**     *      */    private View mContentView;    /**     * 构造函数     *      * @param context Context     * @param layoutId ListView、GridView或者其他AbsListVew子类的 Item View的资源布局id     */    protected CommonViewHolder(Context context, ViewGroup parent, int layoutId) {        mContentView = LayoutInflater.from(context).inflate(layoutId, parent, false);        mContentView.setTag(this);    }    /**     * 获取CommonViewHolder,当convertView为空的时候从布局xml装载item view,     * 并且将该CommonViewHolder设置为convertView的tag, 便于复用convertView.     *      * @param context Context     * @param convertView Item view     * @param layoutId 布局资源id, 例如R.layout.my_listview_item.     * @return 通用的CommonViewHolder实例     */    public static CommonViewHolder getViewHolder(Context context, View convertView,            ViewGroup parent, int layoutId) {        context = (context == null && parent != null) ? parent.getContext() : context;        CommonViewHolder viewHolder = null;        if (convertView == null) {            viewHolder = new CommonViewHolder(context, parent, layoutId);        } else {            viewHolder = (CommonViewHolder) convertView.getTag();        }        // 将当前item view设置为ViewFinder要查找的root view, 这一步不能搞错,否则查找不到对象的view        // ViewFinder.initContentView(viewHolder.getContentView());        return viewHolder;    }    /**     * @return 当前项的convertView, 在构造函数中装载     */    public View getContentView() {        return mContentView;    }    /**     * 为id为textViewId的TextView设置文本内容     *      * @param textViewId 视图id     * @param text 要设置的文本内容     */    public void setTextForTextView(int textViewId, CharSequence text) {        TextView textView = ViewFinder.findViewById(mContentView, textViewId);        if (textView != null) {            textView.setText(text);        }    }    /**     * 为ImageView设置图片     *      * @param imageViewId ImageView的id, 例如R.id.my_imageview     * @param drawableId Drawable图片的id, 例如R.drawable.my_photo     */    public void setImageForView(int imageViewId, int drawableId) {        ImageView imageView = ViewFinder.findViewById(mContentView, imageViewId);        if (imageView != null) {            imageView.setImageResource(drawableId);        }    }    /**     * 为ImageView设置图片     *      * @param imageViewId ImageView的id, 例如R.id.my_imageview     * @param bmp Bitmap图片     */    public void setImageForView(int imageViewId, Bitmap bmp) {        ImageView imageView = ViewFinder.findViewById(mContentView, imageViewId);        if (imageView != null) {            imageView.setImageBitmap(bmp);        }    }    /**     * 为CheckBox设置是否选中     *      * @param checkViewId CheckBox的id     * @param isCheck 是否选中     */    public void setCheckForCheckBox(int checkViewId, boolean isCheck) {        CheckBox checkBox = ViewFinder.findViewById(mContentView, checkViewId);        if (checkBox != null) {            checkBox.setChecked(isCheck);        }    }    /**     * @param viewId     * @param visibility     */    public void setVisibility(int viewId, int visibility) {        View view = ViewFinder.findViewById(mContentView, viewId);        if (view != null) {            view.setVisibility(visibility);        }    }    /**     * @param viewId     * @param listener     */    public void setOnClickListener(int viewId, OnClickListener listener) {        View view = ViewFinder.findViewById(mContentView, viewId);        if (view != null) {            view.setOnClickListener(listener);        }    }    /**     * @param viewId     * @param listener     */    public void setOnTouchListener(int viewId, OnTouchListener listener) {        View view = ViewFinder.findViewById(mContentView, viewId);        if (view != null) {            view.setOnTouchListener(listener);        }    }}

3.CommonAdapter实现

package com.mycollege.adapter;import java.util.List;import android.content.Context;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import com.mycollege.util.CommonViewHolder;/** * @{# CommonAdapter.java Create on 2015-7-17 下午7:34:54 *  *     class desc:  这是一个通用、抽象的适配器类,覆写了BaseAdapter的getCount, getItem, getItemId, * getView方法,在getView方法中通过 * 通用的CommonViewHolder来对convertView的进行处理,并且缓存convertView中的其他View元素 * ,降低了ListView、GridView 等组件的Adapter和ViewHolder的代码量. * 用户只需要在fillItemData函数中将第position位置里的数据填充到listview或者gridview的第position的view中即可 * ,具体使用实例参考文档. *     <p> *     Copyright: Copyright(c) 2015 *     </p> * @Version 1.0 * Tel 15211164134  * Name 潘传爱 * @Author <a href="15211164134@163.com">Hyca</a> *  */public abstract class CommonAdapter<T> extends BaseAdapter {    /**     * Context     */    Context mContext;    /**     * 要展示的数据列表     */    List<T> mData;    /**     * 每一项的布局id,例如R.layout.my_listview_item.     */    private int mItemLayoutId = -1;    /**     * @param context Context     * @param itemLayoutResId     *            每一项(适用于listview、gridview等AbsListView子类)的布局资源id,例如R.layout.     *            my_listview_item.     * @param dataSource 数据源     */    public CommonAdapter(Context context, int itemLayoutResId, List<T> dataSource) {        checkParams(context, itemLayoutResId, dataSource);        mContext = context;        mItemLayoutId = itemLayoutResId;        mData = dataSource;    }    /**     * 检查参数的有效性     *      * @param context     * @param itemLayoutResId     * @param dataSource     */    private void checkParams(Context context, int itemLayoutResId, List<T> dataSource) {        if (context == null || itemLayoutResId < 0 || dataSource == null) {            throw new RuntimeException(                    "context == null || itemLayoutResId < 0 || dataSource == null, please check your params");        }    }    /**     * 返回数据的总数     */    @Override    public int getCount() {        return mData.size();    }    /**     * 返回position位置的数据     */    @Override    public T getItem(int position) {        return mData.get(position);    }    /**     * item id, 返回position     */    @Override    public long getItemId(int position) {        return position;    }    /**     * 返回position位置的view, 即listview、gridview的第postion个view     */    @Override    public View getView(int position, View convertView, ViewGroup parent) {        // 获取ViewHolder        CommonViewHolder viewHolder = CommonViewHolder.getViewHolder(mContext, convertView, parent,                mItemLayoutId);        // 填充数据        fillItemData(viewHolder, position, getItem(position));        // 返回convertview        return viewHolder.getContentView();    }    /**     * 用户必须覆写该方法来讲数据填充到视图中     *      * @param viewHolder 通用的ViewHolder, 里面会装载listview,     *            gridview等组件的每一项的视图,并且缓存其子view     * @param item 数据源的第position项数据     */    protected abstract void fillItemData(CommonViewHolder viewHolder, int position, T item);}

4.万能适配器的使用代码(这里的参数你可以看一下源码)

CommonAdapter<AsAccountSecureEntity> adapter = new CommonAdapter<AsAccountSecureEntity>(this, R.layout.item_asaccountsecure, getListAsAccountSecureEntity()) {@Overrideprotected void fillItemData(CommonViewHolder viewHolder, int position,AsAccountSecureEntity item) {viewHolder.setTextForTextView(R.id.tv_accountsecure, item.name);viewHolder.setTextForTextView(R.id.tv_accountsecurevalue, item.value);//viewHolder.setImageForView(R.id.iv_accountsecure, item.drawableLeft);//viewHolder.setImageForView(R.id.iv_accountsecureclick, item.drawableRight);}};


源码下载地址:http://download.csdn.net/detail/pcaxb/9037975


0 0
原创粉丝点击