Android源码看设计模式(六)--------关于适配器模式ListView的相关分析

适配器模式

定义:

适配器模式把一个类的接口转换成客户端所期待的另一种接口,从而使原本接口不匹配而无法一起工作的两个类能在一起工作

使用场景

1、系统需要使用现在的类,而此类的借口不符合系统的需要,即接口不兼容
2、想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括可能将来引进的类一起工作
3、需要一个统一的输出接口,而输入端的类型不可预知

适配器模式写法

适配器模式分两种类型其UML图如下:
1、类适配器模式
这里写图片描述

  • 目标(Target)角色:这就是所期待得到的接口。注意:由于这里讨论的是类适配器模式,因此目标不可以是类
  • 源(Adapee)角色:现在需要适配的接口。
  • 适配器(Adaper)角色:适配器类是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是具体类

    我们知道额定电压是220V,但是我们真正使用的时候都需要转换一下,比如说手机充电器的电压为5V,那么适配器就是起这个转换的作用,代码如下:

//Target角色
public interface FiveVolt{
    public int getVolt5();
}

//Adaptee角色,需要被转换的角色
public class Volt220{
    public int getVolt220{} {
        return 220;
    }
}

//Adapter角色,将220V的电压转换成5V的电压
public class VoltAdapter extends Volt220 implements FiveVolt{
    @Override
    public int getVolt5() {
        return 5;
    }
}

//调用
 VoltAdapter adapter = new VoltAdapter();
 adapter.getVolt5();

2、对象适配器模式
这里写图片描述

  • 对象的适配依赖于对象的组合,而不是类适配中的继承,我们直接用例子说明
//Target角色
public interface FiveVolt{
    public int getVolt5();
}

//Adaptee角色,需要被转换的对象
public class Volt220{
    public int getVolt220(){
        return 220;
    }
}

//对象适配器模式
public class VoltAdapter implements FiveVolt{
    Volt220 mVolt220;
    public VoltAdapter(Volt220 adaptee) {
        mVolt220 = adaptee;
    }
    public int getVolt220() {
        return mVolt220.getVolt220();
    }
    @Override
    public int getVolt5() {
        return 5;
    }
}

//调用
 VoltAdapter adapter = new VoltAdapter(new Volt220());
 adapter.getVolt5();

这种实现方式直接将要被适配的对象传递到Adapter中,使用组合的形式实现接口兼容的效果,这种比类适配器方式更加灵活,而且被适配对象中的方法不会暴露出来,而类适配器中由于继承了被适配对象,因此Adapter类中会出现被适配对象类的方法,这使得Adapter中出现一些奇怪的接口,用户使用不方便,因此推荐使用对象适配器

ListView中的适配器模式分析

由于RecyclerView是对ListView的一个优化和提高,其中的核心内容是基本一致的,所以在借助ListView来简要说明适配器模式

在实际开发中Adapter通常还应用于输入类型不确定但是输出类型统一的情况,比如说ListView,itemView是各不相同的,但是最终都是属于View类型的,ListView只是需要知道getView返回的是View即可,Adapter用来隔离变化,将ListView需要的关于itemVeiw接口抽象到Adapter对象中,并且在ListView内服调用Adapter这些接口完成布局操作,这样只要实现了Adapter的接口,并且将该Adapter设置给ListView,ListView就可以按照用户设定的UI效果显示每一条数据

我们先来看看ListView的源码:

//发现其中没有Adapter
public class ListView extends AbsListView {
   ......
}

但是ListView是继承AbsListView,AbsListView是一个列表控件的抽象,我们跟进:

public abstract class AbsListView extends AdapterView<ListAdapter> implements TextWatcher,
        ViewTreeObserver.OnGlobalLayoutListener, Filter.FilterListener,
        ViewTreeObserver.OnTouchModeChangeListener,
        RemoteViewsAdapter.RemoteAdapterConnectionCallback {

   ListAdapter mAdapter;
 @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
      //注册一个观察者
      if (mAdapter != null && mDataSetObserver == null) {
          mDataSetObserver = new AdapterDataSetObserver();
          mAdapter.registerDataSetObserver(mDataSetObserver);
          mDataChanged = true;
          mOldItemCount = mItemCount;
          //获得Item的数量
          mItemCount = mAdapter.getCount();
      }
    }

//子类重写layoutChildren()方法来布局子视图
protected void onLayout(boolean changed, int l, int t, int r, int b) {
     super.onLayout(changed, l, t, r, b);
      mInLayout = true;
      final int childCount = getChildCount();
      if (changed) {
          for (int i = 0; i < childCount; i++) {
              getChildAt(i).forceLayout();
          }
          mRecycler.markChildrenDirty();
      }
      //布局Child View
      layoutChildren();
      mInLayout = false;

      mOverscrollMax = (b - t) / OVERSCROLL_LIMIT_DIVISOR;


      if (mFastScroll != null) {
          mFastScroll.onItemCountChanged(getChildCount(), mItemCount);
      }
  }

}

在ListView中Target角色就是View,Adapter就是将ItemView输出为View的角色,Adaptee就是需要被处理的ItemVeiw,通过增加Adapter层将ItemView的操作抽象起来,ListView等集合视图通过Adapter对象获得Item的个数、数据、ItemView等从而达到适配各种数据、各种Item视图的效果。其中千变万化的部分交由用户处理,通过将getCount、getItem、getView等方法抽象出来,也就是将ItemView的构造方法交由用户处理,以达到无限适配的目的

Android源码设计模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值