适配器模式,手写ListView体验适配器"/>
Android适配器模式,手写ListView体验适配器
文章目录
- 适配器模式
- 一. 生活小场景
- 二. 适配器模式定义
- 三. 代码小案例
- 四. RecyclerView的适配器模式
- 五. 手写ListView体验适配器模式
适配器模式
一. 生活小场景
生活中我们将风能转换成我们的电能,如果说我们直接拿到风能,能够把我们的电灯发亮吗?是不行的,对不对,所以这是两个不能够兼容的东西,风能是不能够直接把我们的电灯泡点亮的,那怎么办?只能通过发电机将我们的风能转换成我们的电能,再通过电能去点亮电灯,所以我们的发电机就相当于适配器,它把两个不能兼容的接口,让他们兼容在了一起,宏观上来说也是风能点亮了我们的灯泡。
二. 适配器模式定义
适配器模式 (Adapter Pattern) 是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。
三. 代码小案例
我们这里举例一个电脑通过usb链接显示器的hdmi的例子。
/*** 目标*/
public interface Target {void method();
}
/*** 具体目标是需要一个HDMI的接口*/
public class ConcreteTarget implements Target{@Overridepublic 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{@Overridepublic 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;}@Overridepublic void method() {//拿到源数据adaptee.method2();//这句日志可以理解为转接头,源数据--->目标数据Log.w("simple Adapter", "使用了USB转HDMI线,现在可以使用在HDMI线上了");}
}
测试代码:
public class TestActivity extends AppCompatActivity {@Overrideprotected 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两个接口成功了。
小结:
- 两个不兼容的内容进行了桥接整合,通过中介者Adapter进行连接。
- 希望有一个类转换成另外一个类,但是两个类不兼容,又希望他们能一起工作,那就比较适合使用我们的适配器模式了,提高类的复用。
四. RecyclerView的适配器模式
我们看下面这张图,我们的app的列表是会有很多的数据,数据都是存在集合上面的,但是我们的数据,也就是我们的集合是不能直接添加到我们的ViewGroup上面去的,为什么说是ViewGroup呢,因为列表嘛,肯定不会只有一个子view,数据是不能直接通过addView的方式直接添加到我们的视图上面去显示的。
所以我们需要做一个中转,需要一个适配器Adapter,它做什么工作,它把数据给改了,把集合中的数据改成一个个对应的View,然后再把这些View,通过addView就可以添加到我们的视图上面去了,
接下来我们写个Demo,感受一下适配器:
测试用的Activity
public class TestActivity extends AppCompatActivity {private RecyclerView recyclerView;@Overrideprotected 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@Overridepublic MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view = LayoutInflater.from(mContext).inflate(R.layout.item_test, parent, false);return new MyViewHolder(view);}@Overridepublic void onBindViewHolder(@NonNull MyViewHolder holder, int position) {String data = this.mData.get(position);holder.textView.setText(data);}@Overridepublic 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=""android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><TextViewandroid: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=""android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical"><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recyclerview"android:layout_width="match_parent"android:layout_height="match_parent"/></LinearLayout>
最终的运行结果:
这就是一个经典的适配器模式的例子,也很常用,通过适配器将集合中的数据进行中转,再通过适配器addView。
五. 手写ListView体验适配器模式
我们手写自定义一个适配器,体验一下适配器模式的用途。
/*** 手写简单的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();//获取Viewpublic 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;}@Overridepublic int getCount() {return mItems.size();}@Overridepublic 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;@Overrideprotected 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=""android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical"><com.example.myapplication.TestListViewandroid: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=""android:orientation="vertical"android:layout_width="match_parent"android:layout_height="wrap_content"></TextView>
测试结果
更多推荐
Android适配器模式,手写ListView体验适配器
发布评论