文档章节

android开发笔记之打造终极适配器

Mr_Nice
 Mr_Nice
发布于 2016/05/22 20:00
字数 2003
阅读 1
收藏 0
点赞 2
评论 0

大家看到这个标题是不是觉得很诧异呢?什么叫终极适配器,其实就是这种适配器是万能的,所有需要使用适配器的组件,都可用这一个适配器就行。

既然这样,就来讲讲吧。

效果:

这里写图片描述

当然这是个简单的布局,用普通的适配器也可以实现,这里只是用它来做个例子,用终极适配器的话,以后你换其他布局,适配器是不用变的,减少了很多代码。

首先普通的适配器的写法是:

public class MyAdapter extends BaseAdapter{

    private Context mContext;
    private List<Bean> mDatas;
    private LayoutInflater mLayoutInflater;
    private int mResId;
    public MyAdapter(Context context,List<Bean> data, int resId) {
        mContext = context;
        mDatas = data;
        mLayoutInflater = LayoutInflater.from(mContext);
        mResId = resId;
    }
    @Override
    public int getCount() {
        return mDatas.size();
    }
    @Override
    public Object 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) {
        Bean bean = mDatas.get(position);
        ViewHolder holder;
        if (convertView == null) {
            convertView= mLayoutInflater.inflate(R.layout.myitem, parent, false);
            holder = new ViewHolder();
            holder.title_Tv = (TextView) convertView.findViewById(R.id.title_Tv);
            holder.desc_Tv = (TextView) convertView.findViewById(R.id.desc_Tv);
            holder.time_Tv = (TextView) convertView.findViewById(R.id.time_Tv);
            holder.phone_Tv = (TextView) convertView.findViewById(R.id.phone_Tv);
            convertView.setTag(holder);
        }else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.title_Tv.setText(bean.getTitle());
        holder.desc_Tv.setText(bean.getDesc());
        holder.time_Tv.setText(bean.getTime());
        holder.phone_Tv.setText(bean.getPhone());
        return convertView;
    }   
    static class ViewHolder {
        TextView title_Tv;        //标题
        TextView desc_Tv;         //简介
        TextView time_Tv;         //时间
        TextView phone_Tv;        //电话
    }
}

制作终极适配器的步骤:

首先我们得分析哪些代码是不变的,哪些是可变的,这样才能确定哪些代码能够减少。

这三个重写的方法应该是不变的。

@Override
    public int getCount() {
        return mDatas.size();
    }
    @Override
    public Object getItem(int position) {
        return mDatas.get(position);
    }
    @Override
    public long getItemId(int position) {
        return position;
    }

还有这些代码

        ViewHolder holder;
        if (convertView == null) {
            convertView= mLayoutInflater.inflate(R.layout.myitem, parent, false);
            holder = new ViewHolder();
            holder.title_Tv = (TextView) convertView.findViewById(R.id.title_Tv);
            holder.desc_Tv = (TextView) convertView.findViewById(R.id.desc_Tv);
            holder.time_Tv = (TextView) convertView.findViewById(R.id.time_Tv);
            holder.phone_Tv = (TextView) convertView.findViewById(R.id.phone_Tv);
            convertView.setTag(holder);
        }else {
            holder = (ViewHolder) convertView.getTag();
        }

只不过findViewById我们需要处理一下。所以我们应该把这些不变的代码抽取出来,不应该让用户重复写这些代码。

把这些代码抽取出来,当然这些代码都应该放在ViewHolder中

ViewHolder holder;
        if (convertView == null) {
            convertView= mLayoutInflater.inflate(R.layout.myitem, parent, false);
            holder = new ViewHolder();
        }else {
            holder = (ViewHolder) convertView.getTag();
        }

新建一个类 ViewHolder.java

public class ViewHolder {
    private View mConvertView;
//ViewHolder构造函数,只有当convertView为空的时候才创建
    public ViewHolder(Context context,View convertView, ViewGroup parent, int layouId) {
        convertView = LayoutInflater.from(context).inflate(layouId,parent,false);
        convertView.setTag(this);       //将其setTag()
        mConvertView = convertView;
    }
    //返回一个ViewHolder对象
    public static ViewHolder getHolder(Context context, View convertView, ViewGroup parent, int layoutId) {
        if (convertView == null) {
            return new ViewHolder(context,convertView,parent,layoutId);
        }else {
            return (ViewHolder) convertView.getTag();
        }
    }
}

传过来的参数包括:Context context, View convertView, ViewGroup parent, int layoutId,这些参数都是加载布局文件所需要的。

然后就是这些代码需要抽取了:

holder.title_Tv = (TextView) convertView.findViewById(R.id.title_Tv);
            holder.desc_Tv = (TextView) convertView.findViewById(R.id.desc_Tv);
            holder.time_Tv = (TextView) convertView.findViewById(R.id.time_Tv);
            holder.phone_Tv = (TextView) convertView.findViewById(R.id.phone_Tv);

新建方法:

public class ViewHolder {
    //用来存布局中的各个组件,以键值对形式
    private SparseArray<View> mViews = new SparseArray<>();
    //返回一个View的子类对象,因为不确定用户布局有什么组件,相当于findViewById
    //这里返回一个泛型,也可以返回一个View或Object
    public <T extends View>T getView(int resId) {
        View view = mViews.get(resId);  //从集合中取出这个组件
        if (view == null) {         //如果为空,说明为第一屏
            view = mConvertView.findViewById(resId);    //从convertView中找
            mViews.put(resId,view);     //再将其以键值对存进去
        }
        return (T) view;
    }
}

接下里的这个返回值就容易了,直接返回就行了

public class ViewHolder {
    /** * @return 返回convertView */
    public View getConvertView() {
        return mConvertView;
    }
}

这部分工作都完了,就只留下了为组件设置数据的那段代码了,这段代码由于是可变的,应该让用户来做,所以设置为抽象方法。

新建一个类 CommonAdapter.java 继承BaseAdapter:

public abstract class CommonAdapter<T> extends BaseAdapter {
    //需要显示的数据,List中的类型为泛型,因为不知道用户的封装Bean
    private List<T> mDatas;
    //上下文
    private Context mContext;
    //布局文件Id
    private int mLayoutId;
    public CommonAdapter(Context context,List<T> data,int layoutId) {
        mDatas = data;
        mContext = context;
        mLayoutId = 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 position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = ViewHolder.getHolder(mContext,convertView, parent, mLayoutId);
        setDatas(holder,getItem(position));
        return holder.getConvertView();
    }

    /** * 为各个item中的控件设置数据 * @param holder ViewHolder * @param object 从集合中所取的一个对象 */
    public abstract void setDatas(ViewHolder holder, Object object);
}

到这里就把刚才那段代码全部抽取出来了,那再来看一下如何使用吧。

使用步骤:

①添加ListView, 找ListView 这些步骤是一样的。

②新建一个 Adapter 继承 CommonAdapter

public class MagicAdapter extends CommonAdapter<Bean> {
    public MagicAdapter(Context context, List<Bean> data, int layoutId) {
        super(context, data, layoutId);
    }
    @Override
    public void setDatas(ViewHolder holder, Object object) {
        Bean bean = (Bean) object;
        ((TextView)holder.getView(R.id.title_Tv)).setText(bean.getTitle());
        ((TextView)holder.getView(R.id.desc_Tv)).setText(bean.getDesc());
        ((TextView)holder.getView(R.id.time_Tv)).setText(bean.getTime());
        ((TextView)holder.getView(R.id.phone_Tv)).setText(bean.getPhone());
    }
}

注:

这里写图片描述

③为ListView设置适配器

//为listView设置适配器
        mListView.setAdapter(new MagicAdapter(this,mDatas,R.layout.listview_item));

到这里就实现了万能的适配器了,是不是减少了很多代码。我们知道java三大特性是封装、继承、多态。这篇例子可以锻炼一下大家的封装能力。大家试试吧

核心代码:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<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.briup.universal.MainActivity">

    <ListView  android:id="@+id/listView" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
</RelativeLayout>

listview_item.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">
    <TextView  android:layout_marginTop="12dp" android:layout_marginLeft="12dp" android:textColor="#000" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20sp" android:text="新技能get" android:id="@+id/title_Tv"/>
    <TextView  android:layout_marginLeft="12dp" android:layout_marginTop="10dp" android:textSize="18sp" android:textColor="#CDCDCD" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="打造万能适配器" android:layout_below="@id/title_Tv" android:id="@+id/desc_Tv"/>
    <TextView  android:id="@+id/time_Tv" android:layout_marginTop="10dp" android:layout_marginLeft="12dp" android:text="2016-5-21" android:layout_below="@id/desc_Tv" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
    <TextView  android:id="@+id/phone_Tv" android:text="10086" android:layout_marginRight="12dp" android:layout_alignParentRight="true" android:layout_alignBaseline="@id/time_Tv" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
</RelativeLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private ListView mListView;
    private List<Bean> mDatas;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        initView();
        //为listView设置适配器
        mListView.setAdapter(new MagicAdapter(this,mDatas,R.layout.listview_item));
    }

    /** * 初始化组件 */
    private void initView() {
        mListView = (ListView) findViewById(R.id.listView);
    }

    /** * 初始化数据 */
    private void initData() {
        mDatas = new ArrayList<>();
        //模拟数据
        for (int i=0; i < 6; i++) {
            Bean bean = new Bean("新技能" +i,"打造万能适配器"+ i,"2016-5-22","10086");
            mDatas.add(bean);
        }
    }
}

ViewHolder.java

public class ViewHolder {
    private View mConvertView;
    //用来存布局中的各个组件,以键值对形式
    private SparseArray<View> mViews = new SparseArray<>();
    //ViewHolder构造函数,只有当convertView为空的时候才创建
    public ViewHolder(Context context,View convertView, ViewGroup parent, int layouId) {
        convertView = LayoutInflater.from(context).inflate(layouId,parent,false);
        convertView.setTag(this);       //将其setTag()
        mConvertView = convertView;
    }
    //返回一个ViewHolder对象
    public static ViewHolder getHolder(Context context, View convertView, ViewGroup parent, int layoutId) {
        if (convertView == null) {
            return new ViewHolder(context,convertView,parent,layoutId);
        }else {
            return (ViewHolder) convertView.getTag();
        }
    }
    //返回一个View的子类对象,因为不确定用户布局有什么组件,相当于findViewById
    //这里返回一个泛型,也可以返回一个View或Object
    public <T extends View>T getView(int resId) {
        View view = mViews.get(resId);  //从集合中取出这个组件
        if (view == null) {         //如果为空,说明为第一屏
            view = mConvertView.findViewById(resId);    //从convertView中找
            mViews.put(resId,view);     //再将其以键值对存进去
        }
        return (T) view;
    }

    /** * @return 返回convertView */
    public View getConvertView() {
        return mConvertView;
    }

}

CommonAdapter.java

public abstract class CommonAdapter<T> extends BaseAdapter {
    //需要显示的数据,List中的类型为泛型,因为不知道用户的封装Bean
    private List<T> mDatas;
    //上下文
    private Context mContext;
    //布局文件Id
    private int mLayoutId;
    public CommonAdapter(Context context,List<T> data,int layoutId) {
        mDatas = data;
        mContext = context;
        mLayoutId = 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 position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = ViewHolder.getHolder(mContext,convertView, parent, mLayoutId);
        setDatas(holder,getItem(position));
        return holder.getConvertView();
    }

    /** * 为各个item中的控件设置数据 * @param holder ViewHolder * @param object 从集合中所取的一个对象 */
    public abstract void setDatas(ViewHolder holder, Object object);
}

Bean.java

public class Bean {
    private String title;       //标题
    private String desc;        //简介
    private String time;        //时间
    private String phone;       //电话

    public Bean(String title, String desc, String time, String phone) {
        this.title = title;
        this.desc = desc;
        this.time = time;
        this.phone = phone;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}

MagicAdapter.java

public class MagicAdapter extends CommonAdapter<Bean> {
    public MagicAdapter(Context context, List<Bean> data, int layoutId) {
        super(context, data, layoutId);
    }
    @Override
    public void setDatas(ViewHolder holder, Object object) {
        Bean bean = (Bean) object;
        ((TextView)holder.getView(R.id.title_Tv)).setText(bean.getTitle());
        ((TextView)holder.getView(R.id.desc_Tv)).setText(bean.getDesc());
        ((TextView)holder.getView(R.id.time_Tv)).setText(bean.getTime());
        ((TextView)holder.getView(R.id.phone_Tv)).setText(bean.getPhone());
    }
}

源码下载:http://download.csdn.net

© 著作权归作者所有

共有 人打赏支持
Mr_Nice
粉丝 0
博文 47
码字总数 39947
作品 0
广州
android开发笔记之2012版辅助开发工具包(ADT)新功能特性介绍及安装使用

原文链接:http://android.eoe.cn/topic/androidsdk 2012年的Android辅助设备开发工具包(ADK)是Android开放设备协议(AOA)设备的最新参考实现,它被用于帮助Android硬件辅助设备开发者 和...

sisuad
2013/07/09
0
0
ViewPager一:结合Fragment使用

平时都是打开一个Word来记笔记,现在发现不如写个博文,又不容易丢失,又方便。所以,本次开始,代码一律用截图上传。 接触android开始,就频繁接触android.support.v4包里面的这个向下兼容类...

熊西西77
06/26
0
0
Kiwi:来自xda-developers拥有暗色主题的超快速Chrome浏览器

据外媒报道,几乎在移动软件商城刚出现的时候就形成了这样一个现象:比起Android第三方应用程序开发人员更倾向于iOS。这种差异不仅发生在移动平台早期并且一直持续到现在。尽管Android在全球...

稿源:cnBeta.COM
06/24
0
0
android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码

Android精选源码 android模仿支付宝app”记账本”模块源码(http://www.apkbus.com/thread-600413-1-1.html) android一个超轻量级剪贴板历史记录管理软件源码(http://www.apkbus.com/thread-6...

逆鳞龙
06/26
0
0
开源框架BaseRecyclerViewAdapterHelper使用——RecyclerView万能适配器

前言 主要声明三点 第一: 关于本文的BaseRecyclerViewAdapterHelper用法,自然是转载的官方原文。或许有的人会很疑惑原文写的那么清除那么完善,为什么我还要写一篇几乎一模一样的?是为了蹭...

猜火车_
2017/08/14
0
0
Android进阶之旅与你同行

1.分享的简介 之所以选择内涵段子,是因为这个项目无论从用户体验还是性能方面都很不错,虽然功能不多但是技术上涉及的部分比较多。主要内容有Android源码阅读设计模式分析,以及第三方框架源...

红橙Darren
2017/02/03
0
0
【Android游戏开发二十三】自定义ListView【通用】适配器并实现监听控件!

李华明Himi 原创,转载务必在明显处注明: 转载自【黑米GameDev街区】 原文链接: http://www.himigame.com/android-game/374.html ListView :在Android应用开发过程中属于最常用的系统组件之...

迷途d书童
2012/03/19
0
0
Cocos2dx游戏开发系列笔记1:一个崭新的开始,cocos2dx2.2+ndkr9+Cygwin

Android开发者做cocos2dx最大的绊脚石,不是c++,而是环境的搭建... 骨头也是费了半天劲才终于在真机上看到了那个类似猕猴桃的头,这里简单记录一下。 环境:(算比较新了2013.11.17) coco...

懒骨头
2013/12/09
0
0
Cocos2dx游戏开发系列笔记9:android手机上运行《战神传说》,并解决横竖屏即分辨率自适应

上节说到cygwin下成功编译出so文件,下面我们要把游戏运行在android上。 开始干活! 其实步骤可以参考 Cocos2dx游戏开发系列笔记6:怎样让《萝莉快跑》的例子运行在vs和手机上 1 用eclipse打...

懒骨头
2013/12/09
0
0
Android深入浅出系列之Bluetooth—蓝牙操作(一)

  一:什么是蓝牙     1:Bluetooth是目前使用最广泛的无线通讯协议,近距离无线通讯的标准。传说瑞典有个国王特别爱吃蓝莓导致自己的牙齿天天都是蓝色的,在他执政期间这位国王非常善...

芋头被人用掉了
2015/05/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

PostgresSQL 查看当前schema下所有的函数/存储过程

selectroutine_name from information_schema.routineswhere routine_catalog = 'YourDBName'and routine_schema = 'YourSchemaName'order by routine_name;...

Leyxiao
4分钟前
0
0
去除bootstrapValidator 的校验结果

$("#form").data('bootstrapValidator').destroy();//会报没有这个方法,很奇怪 $('#form').data('bootstrapValidator',null); $('#form').bootstrapValidator();...

暗中观察
5分钟前
0
0
java环境安装

1、首先下载jdk安装包,一般去官网,官网需要登录才可以下载。 2、下载完成双击运行,想改路径改下路径,比较简单。安装jdk安装完,会弹出个窗口,提示开始安装jre的位置,我这里窗口比较奇葩...

朝如青丝暮成雪
7分钟前
0
0
Linux Command

Copy with progress rsync -r --progress source dest

Lyle_W
7分钟前
0
0
个灯数据营销,帮你找回被浪费的广告费

近日,个灯受邀出席被喻为广告营销业界的年度盛会——第八届梅花网传播业大展北京站的活动。 在展会上,个灯总经理严雯婷女士带来了《数据增能,营销智能》的主题演讲,以理论与实践相结合的...

个推
9分钟前
0
0
java的反射机制理解

一、概念说明 java的反射机制,是在运行状态下,可以动态获取任意一个类的属性和方法;可以动态调用一个对象任意方法; 二、反射相关类 java.lang.Class; //类 java.lang.re...

盼望明天
13分钟前
0
0
nginx反向代理-多端口映射

代码解释 1.1 http:www.baidu.test.com默认是80,访问“/”利用反向代理,然后访问本地8083; 1.2 8083代表本地的前端工程访问地址,前端需要访问后台数据,”/”,继续代理到后台地址9803; ...

lilugirl
15分钟前
0
0
Jfinal使用log4j2打印日志

1,添加maven配置 <properties><log4j2.version>2.11.0</log4j2.version><slf4j.version>1.7.25</slf4j.version></properties> <!--slf4j及log4j2日志 --><dependency> ......

iborder
16分钟前
0
0
如何在Rancher 2.0上快速部署Datadog

Datadog是一种流行的托管监控解决方案,用于聚合和分析分布式系统的指标和事件。从基础架构集成到协作仪表板,Datadog为用户提供了一个简洁的单一窗格视图,用户可以快速查看对其最重要的信息...

RancherLabs
19分钟前
0
0
Java示例演示Functor 和monad

This article was initially an appendix in our Reactive Programming with RxJavabook. However introduction to monads, albeit very much related to reactive programming, didn't suit......

Quan全
37分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部