赞
踩
生活中我们将风能转换成我们的电能,如果说我们直接拿到风能,能够把我们的电灯发亮吗?是不行的,对不对,所以这是两个不能够兼容的东西,风能是不能够直接把我们的电灯泡点亮的,那怎么办?只能通过发电机将我们的风能转换成我们的电能,再通过电能去点亮电灯,所以我们的发电机就相当于适配器,它把两个不能兼容的接口,让他们兼容在了一起,宏观上来说也是风能点亮了我们的灯泡。
适配器模式 (Adapter Pattern) 是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。
我们这里举例一个电脑通过usb链接显示器的hdmi的例子。
/** * 目标 */ public interface Target { void method(); } /** * 具体目标是需要一个HDMI的接口 */ public class ConcreteTarget implements Target{ @Override public void method() { Log.w("simple ConcreteTarget", "我需要使用HDMI接口"); } } /** * 源数据,电脑和屏幕连接 */ public class Adaptee { public void method2() { Log.w("simple Adatee", "我需要使用USB接口"); } } /** * 桥梁连接,继承自源数据Adaptee,并且实现目标数据的接口,意思是两边都不落下,作为桥梁 */ public class Adapter extends Adaptee implements Target{ @Override public void method() { //拿到源数据 super.method2(); //这句日志可以理解为转接头,源数据--->目标数据 Log.w("simple Adapter", "使用了USB转HDMI线,现在可以使用在HDMI线上了"); } }
上面书写的这个适配器模式,可以理解为类层面的适配器模式,类适配器,灵活性不是很高。
我们修改下
/** * 桥梁连接,继承自源数据Adaptee,并且实现目标数据的接口,意思是两边都不落下,作为桥梁 */ public class Adapter extends Adaptee implements Target { private Adaptee adaptee; public Adapter(Adaptee adaptee) { this.adaptee = adaptee; } @Override public void method() { //拿到源数据 adaptee.method2(); //这句日志可以理解为转接头,源数据--->目标数据 Log.w("simple Adapter", "使用了USB转HDMI线,现在可以使用在HDMI线上了"); } }
测试代码:
public class TestActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Adaptee adaptee = new Adaptee();
Adapter adapter = new Adapter(adaptee);
adapter.method();
}
}
从结果看出运行成功,意味着适配器桥接usb和hdmi两个接口成功了。
小结:
我们看下面这张图,我们的app的列表是会有很多的数据,数据都是存在集合上面的,但是我们的数据,也就是我们的集合是不能直接添加到我们的ViewGroup上面去的,为什么说是ViewGroup呢,因为列表嘛,肯定不会只有一个子view,数据是不能直接通过addView的方式直接添加到我们的视图上面去显示的。
所以我们需要做一个中转,需要一个适配器Adapter,它做什么工作,它把数据给改了,把集合中的数据改成一个个对应的View,然后再把这些View,通过addView就可以添加到我们的视图上面去了,
接下来我们写个Demo,感受一下适配器:
测试用的Activity
public class TestActivity extends AppCompatActivity { private RecyclerView recyclerView; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = findViewById(R.id.recyclerview); LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); recyclerView.setLayoutManager(linearLayoutManager); //构建源数据, List<String> data = new ArrayList<>(); data.add("111"); data.add("222"); data.add("333"); MyAdapter myAdapter = new MyAdapter(this, data); recyclerView.setAdapter(myAdapter); } }
适配器
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> { private Context mContext; private List<String> mData; public MyAdapter(Context mContext, List<String> mData) { this.mContext = mContext; this.mData = mData; } @NonNull @Override public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.item_test, parent, false); return new MyViewHolder(view); } @Override public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { String data = this.mData.get(position); holder.textView.setText(data); } @Override public int getItemCount() { return mData.size(); } public static class MyViewHolder extends RecyclerView.ViewHolder { TextView textView; public MyViewHolder(@NonNull View itemView) { super(itemView); textView = itemView.findViewById(R.id.textview); } } }
item子view的xml布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/textview"
android:textSize="30sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="111" />
</LinearLayout>
父布局的xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
最终的运行结果:
这就是一个经典的适配器模式的例子,也很常用,通过适配器将集合中的数据进行中转,再通过适配器addView。
我们手写自定义一个适配器,体验一下适配器模式的用途。
/** * 手写简单的ListView,不考虑复用 */ public class TestListView extends ScrollView { private LinearLayout mContainer; private ListAdapter mAdapter; public TestListView(Context context) { super(context, null); } public TestListView(Context context, AttributeSet attrs) { super(context, attrs, 0); mContainer = new LinearLayout(context); mContainer.setOrientation(LinearLayout.VERTICAL); super.addView(mContainer); } public TestListView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContainer = new LinearLayout(context); mContainer.setOrientation(LinearLayout.VERTICAL); super.addView(mContainer); } public void addView(View child) { mContainer.addView(child); } public void setAdapter(ListAdapter listAdapter) { this.mAdapter = listAdapter; int count = mAdapter.getCount(); for (int i = 0; i < count; i++) { View childView = mAdapter.getView(i, mContainer); mContainer.addView(childView); } } }
先自定义一个抽象类父类适配器,模拟ListView的两个方法,
public abstract class ListAdapter {
//获取多少条
public abstract int getCount();
//获取View
public abstract View getView(int position, ViewGroup viewGroup);
}
实现类
public class MyAdapter extends ListAdapter { private Context mContext; private List<String> mItems; public MyAdapter(Context mContext, List<String> mItems) { this.mContext = mContext; this.mItems = mItems; } @Override public int getCount() { return mItems.size(); } @Override public View getView(int position, ViewGroup viewGroup) { TextView itemView = (TextView) LayoutInflater.from(mContext).inflate(R.layout.item_simple3, null); itemView.setText(mItems.get(position)); return itemView; } }
测试类
public class TestActivity extends AppCompatActivity { TestListView testListView; List<String> mData; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); testListView = findViewById(R.id.testView); mData = new ArrayList<>(); for (int i = 0; i < 100; i++) { mData.add(i + ""); } MyAdapter myAdapter = new MyAdapter(this, mData); testListView.setAdapter(myAdapter); } }
activity_main的xml布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<com.example.myapplication.TestListView
android:id="@+id/testView"
android:layout_width="match_parent"
android:layout_height="match_parent"></com.example.myapplication.TestListView>
</LinearLayout>
itemView的xml布局
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</TextView>
测试结果
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。