Android之ListView的Adapter的复用

在Android开发中一个项目需要在很多地方使用的ListView。既然使用了ListView则不可避免的使用了Adapter,重复写逻辑几乎相同的Adapter也是一件枯燥的事,下面来研究如何复用Adapter.
使用了ListView的两个地方(模拟代码):

一.//第一个ListView
listView.setAdapter(new MyAdapter());
 class MyAdapter extends BaseAdapter{
    //arrayList是设置给ListView数据的集合
       @Override
       public int getCount() {
           return arrayList.size();
       }

       @Override
       public Object getItem(int i) {
           return arrayList.get(i);
       }

       @Override
       public long getItemId(int i) {
           return i;
       }

       @Override
       public View getView(int i, View view, ViewGroup viewGroup) {
          ViewHolder  viewHolder =null;
           if(view == null){
               view = View.inflate(ThemeFragment.this.getActivity(), R.layout.theme_adapt_item,null);
               viewHolder = new ViewHolder();
               viewHolder.icon = (ImageView) view.findViewById(R.id.theme_iv);
               viewHolder.textView = (TextView) view.findViewById(R.id.theme_text);
               view.setTag(viewHolder);
           }else{
               viewHolder = (ViewHolder) view.getTag();
           }
           //给ViewHolder设置值,即给ListView的各个组件设置值
           BitmapHelper.getBitmapUtils().display(viewHolder.icon, GlobalUrl.ICON_URL+theme.themeInfos.get(i).url);
           viewHolder.textView.setText(theme.themeInfos.get(i).des);
           return view;
       }
   }
   //为了优化ListView不可避免的使用了ViewHolder来复用
    static class ViewHolder{
       ImageView  icon;
       TextView   textView;
    }
二.//第二个ListView

listView.setAdapter(new MyAdapter());
 class MyAdapter extends BaseAdapter{
    //arrayList是设置给ListView数据的集合
       @Override
       public int getCount() {
           return arrayList.size();
       }

       @Override
       public Object getItem(int i) {
           return arrayList.get(i);
       }

       @Override
       public long getItemId(int i) {
           return i;
       }

       @Override
       public View getView(int i, View view, ViewGroup viewGroup) {
          ViewHolder  viewHolder =null;
           if(view == null){
               view = View.inflate(HomeFragment.this.getActivity(), R.layout.home_adapt_item, null);
               viewHolder = new ViewHolder();
           viewHolder.item_icon = (ImageView) view.findViewById(R.id.item_icon);
           viewHolder.app_name = (TextView) view.findViewById(R.id.item_title);
           viewHolder.app_size = (TextView) view.findViewById(R.id.item_size);
           viewHolder.app_introduce = (TextView) view.findViewById(R.id.item_bottom);
               view.setTag(viewHolder);
           }else{
               viewHolder = (ViewHolder) view.getTag();
           }
           //给ViewHolder设置值,即给ListView的各个组件设置值
      BitmapHelper.getBitmapUtils().display(this.item_icon, GlobalUrl.ICON_URL + detailAppInfos.iconUrl);
           this.app_name.setText(detailAppInfos.name);
           this.app_size.setText(detailAppInfos.size);
           this.app_introduce.setText(detailAppInfos.des);
           return view;
       }
   }
   //为了优化ListView不可避免的使用了ViewHolder来复用
    static class ViewHolder{
       ImageView item_icon;
       TextView app_name;
       TextView app_size;
       TextView app_introduce;
    }

如上两段代码是在开发过程中经常使用到的,现在对Adapter进行抽取封装:
1.首先Adapter的前三个方法:getCount(),getItem(),getItemId()是完全一样的,通过一个ArrayList来完成。我们抽取的Adapter让子类注入一个ArrayList进来:

 public class DefaultAdapter extends BaseAdapter {
    private List listData;
    public DefaultAdapter(List list){
         this.listData = list;
    }
    @Override
    public int getCount() {
        return listData.size();
    }

    @Override
    public Object getItem(int i) {
        return listData.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        return null;
    }
}

2.此时Adapter中的getView()显示的很臃肿,为了getView()方法的简介,将getView()方法与为了复用的ViewHolder进行进一步修改(针对第二个ListView):

Adapter:

 class MyAdapter extends DefaultAdapter<HomeInfos.DetailAppInfos>{


        public MyAdapter(List list) {
            super(list);
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            ViewHolder viewHolder = null;
            if(view==null){
            //所有的初始化view的方法全部放在ViewHolder的构造方法中
                viewHolder = new ViewHolder();
            }else{
                viewHolder = (ViewHolder) view.getTag();
            }
            //设置数据的方法也放在viewHolder中,而设置的具体数据(集合中的数据)注入进去
            viewHolder.setDetailInfos(homeInfos.list.get(i));
            return viewHolder.getView();
        }
    }

ViewHolder:

static class ViewHolder{
       ImageView item_icon;
       TextView app_name;
       TextView app_size;
       TextView app_introduce;
       //显示的每个条目的View
       private   View view;
       private  BitmapUtils bitmapUtils;
       //集合中的数据,设置给每个ListView条目的
       private HomeInfos.DetailAppInfos detailAppInfos;
       //注入的方法
       public void setDetailInfos(HomeInfos.DetailAppInfos detailAppInfos) {
           this.detailAppInfos = detailAppInfos;
          //注入成功后,刷新view。刷新view即是把集合中的数据设置给viewHolder
           refreshView();
       }

       public ViewHolder(){
           bitmapUtils = BitmapHelper.getBitmapUtils();
           view = View.inflate(UiUtil.getContext(), R.layout.home_adapt_item, null);
           this.item_icon = (ImageView) view.findViewById(R.id.item_icon);
           this.app_name = (TextView) view.findViewById(R.id.item_title);
           this.app_size = (TextView) view.findViewById(R.id.item_size);
           this.app_introduce = (TextView) view.findViewById(R.id.item_bottom);
           view.setTag(this);
       }

       public View getView() {
           return view;
       }
       //集合中的数据设置给viewHolder
       public void refreshView(){
           BitmapHelper.getBitmapUtils().display(this.item_icon, GlobalUrl.ICON_URL + detailAppInfos.iconUrl);
           this.app_name.setText(detailAppInfos.name);
           this.item_rating.setRating((float) detailAppInfos.stars);
           this.app_size.setText(detailAppInfos.size);
           this.app_introduce.setText(detailAppInfos.des);

       }

    }

3.将两个ListView都做如上操作之后会发现,getView变得极其相似了,那么我们可以把它提取到分类中:
此时就会发现一个问题,每个ListView的ViewHolder都不一样,所以我们把ViewHolder与进一部的进行抽象(针对第二个ListView):
BaseViewHolder:

public abstract class BaseViewHolder {

    private View view;
    private BitmapUtils bitmapUtils;
    private T detailInfos;

    public void setDetailInfos(T detailInfos) {
        this.detailInfos = detailInfos;
        refreshView(detailInfos);
    }

    public BaseViewHolder(){
        bitmapUtils = BitmapHelper.getBitmapUtils();
        view = initView();
        view.setTag(this);
    }
   public abstract View   initView();

    public View getView() {
        return view;
    }
    public abstract void refreshView(T detailInfos);

}

经过抽取之后:每个ViewHolder只需要实现两个抽象方法

static class ViewHolder extends BaseViewHolder.DetailAppInfos>{
       ImageView item_icon;
       TextView app_name;
       RatingBar item_rating;
       TextView app_size;
       TextView app_introduce;

       @Override
       public View initView() {
           View   view = View.inflate(UiUtil.getContext(), R.layout.home_adapt_item, null);
           this.item_icon = (ImageView) view.findViewById(R.id.item_icon);
           this.app_name = (TextView) view.findViewById(R.id.item_title);
           this.item_rating = (RatingBar) view.findViewById(R.id.item_rating);
           this.app_size = (TextView) view.findViewById(R.id.item_size);
           this.app_introduce = (TextView) view.findViewById(R.id.item_bottom);
           return  view;
       }
       @Override
       public void refreshView(HomeInfos.DetailAppInfos detailAppInfos){
           BitmapHelper.getBitmapUtils().display(this.item_icon, GlobalUrl.ICON_URL + detailAppInfos.iconUrl);
           this.app_name.setText(detailAppInfos.name);
           this.item_rating.setRating((float) detailAppInfos.stars);
           this.app_size.setText(detailAppInfos.size);
           this.app_introduce.setText(detailAppInfos.des);

       }

    }

4.此时,把getView()提取到抽象中:
对于每个ViewHolder也有了BaseViewHolder,但在getView()中生成具体的ViewHodler时不知道生成哪一个,所以可以定义一个获取子类ViewHolder的抽象方法,让子类返回一个自身的ViewHolder的实现(这儿类似与DAO设计模式中BaseServiceImpl声明一个抽象方法,让子类返回自身Dao的实现因为BaseServiceImpl不知道使用哪个Dao来完成,只能丢给子类来处理).

最终的代码(针对第二个ListView):

class MyAdapter extends DefaultAdapter<HomeInfos.DetailAppInfos>{


        public MyAdapter(List list) {
            super(list);
        }

        @Override
        protected BaseViewHolder getViewHolder() {
            return new ViewHolder();
        }


    }
   static class ViewHolder extends BaseViewHolder<HomeInfos.DetailAppInfos>{
       ImageView item_icon;
       TextView app_name;
       TextView app_size;
       TextView app_introduce;

       @Override
       public View initView() {
           View   view = View.inflate(UiUtil.getContext(), R.layout.home_adapt_item, null);
           this.item_icon = (ImageView) view.findViewById(R.id.item_icon);
           this.app_name = (TextView) view.findViewById(R.id.item_title);
           this.app_size = (TextView) view.findViewById(R.id.item_size);
           this.app_introduce = (TextView) view.findViewById(R.id.item_bottom);
           return  view;
       }
       @Override
       public void refreshView(HomeInfos.DetailAppInfos detailAppInfos){
           BitmapHelper.getBitmapUtils().display(this.item_icon, GlobalUrl.ICON_URL + detailAppInfos.iconUrl);
           this.app_name.setText(detailAppInfos.name);
           this.app_size.setText(detailAppInfos.size);
           this.app_introduce.setText(detailAppInfos.des);

       }

    }

抽象的两个类Adapter和ViewHolder:

public abstract class DefaultAdapter extends BaseAdapter {
    private List listData;
    public DefaultAdapter(List list){
         this.listData = list;
    }
    @Override
    public int getCount() {
        return listData.size();
    }

    @Override
    public Object getItem(int i) {
        return listData.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        BaseViewHolder viewHolder =null;
        if(view == null){

            viewHolder = getViewHolder();

        }else{
            viewHolder = (BaseViewHolder) view.getTag();
        }
        viewHolder.setDetailInfos(listData.get(i));
        return viewHolder.getView();
    }
    protected  abstract BaseViewHolder getViewHolder();
}
public abstract class BaseViewHolder {

    private View view;
    private BitmapUtils bitmapUtils;
    private T detailInfos;

    public void setDetailInfos(T detailInfos) {
        this.detailInfos = detailInfos;
        refreshView(detailInfos);
    }

    public BaseViewHolder(){
        bitmapUtils = BitmapHelper.getBitmapUtils();
        view = initView();
        view.setTag(this);
    }
   public abstract View   initView();

    public View getView() {
        return view;
    }
    public abstract void refreshView(T detailInfos);

}

这样就完成了ListView设置Adapter的抽象,以后需要使用Adapter的地方直接让Adapter继承DefaultAdapter。让ViewHolder实现BaseViewHolder,然后分别实现父类定义的抽象方法(Adapter实现返回自己ViewHolder的方法,ViewHolder实现生成每个条目的View方法和给这个View设置数据的方法)即可。

你可能感兴趣的:(Android开发)