谷歌电子市场开发流程(4)-listview的两层封装

本文介绍了一种高效的ListView封装方法,通过自定义适配器基类减少重复代码,提高开发效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上篇讲到页面的加载初始化,当完成之后会发现每一个代表子标签页的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类去封装起来

@Override
public 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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值