定义
将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
角色说明:
- Adapter(适配器接口):即目标角色,定义把其他类转换为何种接口,也就是我们期望的接口。
- Adaptee(被适配角色):即源角色,一般是已存在的类,需要适配新的接口。
- ConcreteAdapter(具体适配器):实现适配器接口,把源角色接口转换为目标角色期望的接口。
5.5 说明:
类适配器模式只要通过继承源目标类来实现,无需持有源目标对象。
5.6 对象适配器模式与类适配器模式比较
- 类适配器采用了继承的方式来实现;而对象适配器是通过传递对象来实现,这是一种组合的方式。
- 类适配器由于采用了继承,可以重写父类的方法;对象适配器则不能修改对象本身的方法等。
- 适配器通过继承都获得了父类的方法,客户端使用时都会把这些方法暴露出去,增加了一定的使用成本;对象适配器则不会。
- 类适配器只能适配他的父类,这个父类的其他子类都不能适配到;而对象适配器可以适配不同的对象,只要这个对象的类型是同样的。
- 类适配器不需要额外的引用;对象适配器需要额外的引用来保存对象。
总的来说,使用对象适配器比较好。当然具体问题具体分析。
6. 应用场景
- 当想使用一个已经存在的类,但它的接口不符合需求时。
- 当想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作。
7. 优点
- 提高了类的复用性,适配器能让一个类有更广泛的用途。
- 提高了灵活性,更换适配器就能达到不同的效果。不用时也可以随时删掉适配器,对原系统没影响。
- 符合开放封闭原则,不用修改原有代码。没有任何关系的类通过增加适配器就能联系在一起。
8. 缺点
- 过多的使用适配器,会让系统非常零乱,不易整体进行把握。明明调用A接口,却被适配成B接口。
9. Android中的源码分析
说到适配器,ListView
和RecyclerView
就再熟悉不过了,ListView
现在应该很少用了吧,这里就以RecyclerView
来分析。
LayoutManager 用來管理版面配置
官方提供了三種總類
LinearLayoutManager 此類別會將項目 (item) 顯示在垂直或水平的清單中。
GridLayoutManager 此類別會將項目 (item) 顯示於網格中。
StaggeredGridLayoutManager 此類別會將項目 (item) 顯示於交錯網格中。
Adapter 是資料與 RecyclerView 之間的橋樑
使用 RecyclerView.Adapter 時必須實作 RecyclerView.ViewHolder 管理畫面 (ListView 也可設計 ViewHolder 來管以畫面,但沒有強制規定)
9.1 RecyclerView的使用
先来一个RecyclerView
的简单使用例子:
Article.java
===========================================================
public class Article {
private String title;
private String subtitle;
public Article() {
title = "This is title.";
subtitle = "This is subtitle.";
}
public Article(String title, String subtitle) {
this.title = title;
this.subtitle = subtitle;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getSubtitle() {
return subtitle;
}
public void setSubtitle(String subtitle) {
this.subtitle = subtitle;
}
}
===========================================================
這個是清單的每一欄的版面配置,在 ArticleAdapter 中會利用 LayoutInflater 轉成 View。
Item 布局文件 item.xml
===========================================================
===========================================================
Adapter代码
RecyclerView.ViewHolder and RecyclerView.Adapter
繼承 RecyclerView.Adapter 必須在泛型內放入一個繼承 RecyclerView.ViewHolder 的物件,此範例將 ViewHolder 宣告為 MyAdapter 的內部類別,而 ViewHolder 通常用以設定畫面元件。
另外,繼承 RecyclerView.Adapter 還需 Override 三個方法
onCreateViewHolder:初始化畫面元件。
onBindViewHolder:設定畫面元件內容。
getItemCount:取得資料 item 總數。
ArticleAdapter.java
===========================================================
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
/**
* Created by sarah on 08/12/2017.
*/
public class ArticleAdapter extends RecyclerView.Adapter<ArticleAdapter.ViewHolder> {
private List<Article> articles;
public ArticleAdapter(List<Article> articles) {
this.articles = articles; //初始化数据
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item,parent,false);
ViewHolder viewHolder = new ViewHolder(itemView);
return viewHolder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Article article = articles.get(position);
holder.bind(article);
}
@Override
public int getItemCount() {
return articles.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder{
private final TextView subtitle;
private final TextView title;
public ViewHolder(View itemView) {
super(itemView);
title = (TextView)itemView.findViewById(R.id.title);
subtitle = (TextView)itemView.findViewById(R.id.subtitle);
}
public void bind(Article article){
title.setText(article.getTitle());
subtitle.setText(article.getSubtitle());
}
}
}
===========================================================
Activity布局文件 activity_main.xml
===========================================================
程式一開始先放入一百個 Article 近 List 中,之後再交給 ArticleAdapter 將資料顯示到 RecyclerView 中。
MainActivity.java
===========================================================
9.2 总结
RecyclerView
时我们要传递一个Adapter
进去,然后通过复写Adapter
中的onCreateViewHolder()
、onBindViewHolder()
、getItemCount()
等方法以及内部类ViewHolder
。通过不同的Adapter
,我们能够实现不同的布局。上面的MyAdapter
是继承RecyclerView.Adapter
这个类的,而Adapter
实际上是RecyclerView
的内部类。这里的Adapter
就充当了适配器接口,即目标角色,RecyclerView
内部通过Adapter
获取它需要的接口和数据等。至于MyAdapter
,就是具体的适配器,通过它把不同的布局跟RecyclerView
联系起来。最后就是被适配角色,即源角色,这里就是各种不同的item布局。
为什么Android要这么设计呢,想想在一个列表中,我们要展示的布局可能是简单的,也可能是超复杂的,这个布局是未知的,是根据要展示的数据集来决定的;通过适配器模式,就能够把不同的东西都可以转化成同样的接口,系统处理起来就有套路了,同时也无需关心各种千变万化的布局
Reference:
No comments:
Post a Comment