Android进阶学习-打造一个通用的Adapter
2016-04-09 00:00
417 查看
先来看看我们最普通的Adapter是怎样的吧.
代码:
每次写的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了,详情看代码
这样我们就可以使用getHolder方法来去新建或取回一个ViewHolder了,有了ViewHolder还不行,我们还要获取里面的View,这里我们使用泛型去写
这样以后我们就可以获取View并且作相应操作了
下面开始编写我们GeneralParentAdapter了,因为是通用的,所以Adapter对应的Layout就需要以参数的形式传入,mDatas也需要时泛型的.
嗯,这就是那堆让人讨厌的经常反反复复去写的代码
下面是Adapter的getView方法了,这里就要使用到ViewHolder了
然后我们发现,第一行和最后一行也是可以复用的,而且我们需要返回一个converView,那么我们就在ViewHolder添加一个方法吧
继续,我们的Adapter就能用的,但是还不行,我们再把设置内容那里抽取出来,这才是每个Adapter真正的不同之处.现在我们把Adapter变成抽象类,并设置抽象方法setContent
最后我们就可以使用了
ItemBean.java
item_text.xml
调用代码
可以看到我们需要写的代码从一堆变成了短小精悍的几行,但还不够,我们还得上天呢 哈哈.我们再给ViewHolder设置一些通用的方法,无非是什么setText,setBitmap之类的,于是VIewHolder有了...
最后我们继续精简
最后变成了两行代码,咱们就呵呵了...大家还可以根据自己需要去封装更多的方法.
ViewHolder代码:
GeneralParentAdapter代码:
代码:
[code=plain]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了,详情看代码
[code=plain]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,这里我们使用泛型去写
[code=plain] 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也需要时泛型的.
[code=plain]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了
[code=plain]@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添加一个方法吧
[code=plain]public View getConverview() { return this.mConvertview; }
继续,我们的Adapter就能用的,但是还不行,我们再把设置内容那里抽取出来,这才是每个Adapter真正的不同之处.现在我们把Adapter变成抽象类,并设置抽象方法setContent
[code=plain] @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
[code=plain]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
[code=plain]<?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>
调用代码
[code=plain] 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有了...
[code=plain] 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); } }
最后我们继续精简
[code=plain] 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代码:
[code=plain]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代码:
[code=plain]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); }
相关文章推荐
- C#列出所有物理网络适配器的方法
- oracle适配器连接不上的解决办法
- JavaScript代码复用模式详解
- php设计模式 Adapter(适配器模式)
- ListView Adapter优化 实例
- Adapter实现ListView带多选框等状态的自定义控件的注意事项
- 自定义Adapter并通过布局泵LayoutInflater抓取layout模板编辑每一个item实现思路
- Android中的Adapter简单介绍
- ASP.NET的适配器设计模式(Adapter)应用详解
- Android自定义Adapter的ListView的思路及代码
- Android编程中常用适配器及自定义适配器用法实例分析
- ListView的Adapter使用(绑定数据) 之 自定义每一项的布局去绑定数据
- android开发中ListView与Adapter使用要点介绍
- Android自定义Spinner下拉列表(使用ArrayAdapter和自定义Adapter实现)
- PHP中的traits实现代码复用使用实例
- PHP 实现代码复用的一个方法 traits新特性
- Java设计模式之适配器模式简介
- ListView的Adapter使用 之 初学ArrayAdapter String
- Generic adapter class in Python
- 玩转树莓派——安装 Windows 10 IoT Core