谷歌电子市场开发流程(4)-listview的两层封装
来源:互联网 发布:网络用语开屏什么意思 编辑:程序博客网 时间:2024/06/04 18:48
上篇讲到页面的加载初始化,当完成之后会发现每一个代表子标签页的Fragment都需要实现两种方法,onCreateSuccessPage()和onLoad(),其中onCreateSuccessPage()方法是决定在加载成功时Fragment该显示什么,而onLoad()方法则是在请求数据,并将返回的网络状态传递给LoadingPage类,让LoadingPage来决定该选择什么界面加载。
当项目敲到这里,我们就可以考虑如何去实现子标签页面加载成功的显示了,也就是onCreateSuccessPage()方法该如何实现。我们可以想象,知道,每一个首页都大体是一个个ListView进行展示,所以我们可以在onCreateSuccessPage()方法中new一个ListView,下面就是常规的适配器的填充了。
实现四个父类未实现的方法即可
class ListhomeAdapter extends BaseAdapter{ private final List<String> list; public ListhomeAdapter() { super(); list = new ArrayList<String>(); for (int i=0;i<20;i++){ list.add("测试数据" + i); } } @Override public int getCount() { return list.size(); } @Override public String getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder=null; if (convertView==null){ viewHolder=new ViewHolder(); convertView=UIUtils.getView(R.layout.list_home); viewHolder.textView=(TextView)convertView.findViewById(R.id.text_test); convertView.setTag(viewHolder); }else { viewHolder=(ViewHolder)convertView.getTag(); } viewHolder.textView.setText(getItem(position)); return convertView; }}static class ViewHolder{ TextView textView;}
现在,我们来考虑这个问题,我们的项目需要多少个ListView呢,显而易见,ListView使用的场景实在太多,看看上面的代码,如果每一个ListView都要敲这么一大串,简直是一种折磨。那么,来观察上面的代码,我们可以发现除了getView()方法比较繁琐之外,其他三个方法在每一个ListView都会这么写,只不过每一个LIstView填充的数据不同而已,那么,我们能不能将相似的代码抽取出来,封装在一个类中,让代码量大大减少呢?
其实在上篇就已经使用过封装,也提到过封装的好处,那么,封装就势在必行。我们现在要考虑的就是如何去封装?
我们知道,ListView适配器继承的是BaseAdapter,这是android源码提供的一个基类,那么我们也可以为ListView去提供一个适配器基类,将相似的代码在基类中实现,不相同的代码,我们可以使用抽象方法交给子类去实现,而ListViewAdapter只需要继承自定义基类,然后实现基类未实现的方法即可。
思路有了,现在就开始敲代码了。
(第一层封装)
1.自定义MyBaseAdapter类继承BaseAdapter,实现父类未实现的方法。getCount(),getItem(),getItemId(),getView()
2.因为每一个方法都需要数据,而每一个ListView所填充的数据都不一样,因此我们可以在基类中定义一个泛型,通过有参构造函数,让子类在初始化时就将数据传递进来,那么就可以保证泛型使用的安全性。
public class MyBaseAdapter<T> extends BaseAdapter { public ArrayList<T> data; public MyBaseAdapter(ArrayList<T> data) { super(); this.data=data; } @Override public int getCount() { return data.size(); } @Override public T getItem(int position) { return data.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { return null; }}
(第二层封装)
3.现在已经将三个方法封装完成,只剩下getView()方法无法封装,因为getView()方法几乎完全是由子类自己决定的,父类根本不知道如何去实现,那该怎么办呢?
我们来考虑getVie()方法到底做了哪些事:
(1)加载布局文件 convertView=UIUtils。getView(R.layout.a);
(2)根据id找到控件 convertView.findviewbyid();
(3)打一个标记,convertView.setTag();
(4)根据数据,刷新页面
这是所有的getView()方法都必须要做的事情,那么,我们在父类中将这些事的流程完成,遇到无法完成的就可以交个子类去实现就可以了;
4.新建一个MyBaseHolder类,这就是代表ViewHolder,在这个类中实现getView()做的事。
(1)加载布局文件,MyBaseHolder不知如何加载,定义一个抽象方法initView(),将其返回值作为布局文件的View
(2)根据id找到控件,这件事是需要在子类实现的,子类一旦实现了initView()方法,这件事就将会自动完成,所以在此类中不需要做,或者说,在initView()已经完成
(3)打开一个标记,定义一个View mRootView变量,在构造方法中使用initView()对其进行初始化,然后再mRootView.setTag();
(4)根据数据,刷新页面,基类仍然不知道该如何刷新页面,因此定义抽象方法,但是必须根据数据来刷新,数据从何处来?那么我就需要给RefreshPage()方法设置一个数据参数,这个参数是什么类型,使用泛型就ok了,我必须要将数据传递给MyBaseHolder类中,这时就需要想到get set方法,可以通过set方法将数据传递过来,那么整体代码逻辑就很清晰了。
public abstract class MyBaseHolder<T> { private final View mRootView; private T data; public MyBaseHolder(){ mRootView = initView(); mRootView.setTag(this); } public T getData() { return data; } public void setData(T data) { this.data = data; RefreshPage(data); } public View getmRootView() { return mRootView; } //1.加载布局页面 2.格局id找到控件 public abstract View initView(); //刷新页面 public abstract void RefreshPage(T data);}
最后,在MyBaseAdapter中将getView()方法通过MyBaseHolder类去封装起来
@Overridepublic View getView(int position, View convertView, ViewGroup parent) { MyBaseHolder myBaseHolder=null; if (convertView==null){ myBaseHolder=getHolder(); }else { myBaseHolder=(MyBaseHolder)convertView.getTag(); } myBaseHolder.setData(getItem(position)); return myBaseHolder.getmRootView();}public abstract MyBaseHolder<T> getHolder();
这里要注意MyBaseHolder不能直接new出来,因为new出来就必须实现未实现的方法,但是MyBaseAdapter类也不知道该如何去实现,所以,直接在MyBaseAdapter中设置一个抽象方法,交给子类去实现。
至此,两层封装已完成,以后使用ListView时,只需要继承MyBaseAdapter,实现相应构造方法传递数据和getHolder()方法设置item。
- 谷歌电子市场开发流程(4)-listview的两层封装
- 谷歌电子市场开发流程(6)-xutils的使用
- 谷歌电子市场开发流程(6)-xutils的使用
- 谷歌电子市场开发流程(7)-单例模式
- 谷歌电子市场开发流程(8)-自定义控件
- 谷歌电子市场开发流程(9)-线程,线程池
- 谷歌电子市场开发流程(3)-关于加载界面的处理
- 谷歌电子市场开发流程(5)-关于加载更多页面的处理
- 谷歌电子市场开发流程(10)-回调与观察者模式
- 谷歌电子市场开发记录(1)-开发前的准备
- 谷歌电子市场开发记录(2)-框架搭建
- 谷歌电子市场笔记4
- 谷歌电子市场第4天总结
- 谷歌电子市场
- 指令汇C电子市场开发(一) ActionBar的使用
- 谷歌电子市场笔记1
- 谷歌电子市场笔记2
- 谷歌电子市场笔记3
- Spring Security 实现权限登陆配置
- Linux 下route命令详解
- MVP介绍以及优化封装
- 欢迎使用CSDN-markdown编辑器
- 编译keil 遇到File has been changed outside the editor,reload?问题解决方法
- 谷歌电子市场开发流程(4)-listview的两层封装
- 剑指offer--字符串的排列
- ES6和React知识思想
- 剑指Offer----二进制中1的个数
- 小白学分布式开发5——CAP理论
- Spring框架02
- Android和H5、JS进行交互调用
- Intellij IDEA带参数启动Springboot注意事项
- JS实现从XML中获取省份和城市信息_二级联动