谷歌电子市场开发流程(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。

原创粉丝点击