一种优雅的方式来使用RecyclerView
使得RecyclerView各种情况的多类型条目更简单!
示例图片
![]() | ![]() | ![]() |
![]() | ![]() | ![]() |
下载体验
核心思想
想必大家都遇到过,在一个列表中显示不同样式的需求。在RecyclerView中可以通过ViewType进行区分,如果样式特别多的时候就会使得代码非常冗余,不利于开发及维护。那么有没有一种优雅的方法解决这个问题呢?
技术经理给你说,接下来的项目由你负责,明天下班前把排期同步出来。这时你应该怎么做?由于你是Android端的RD,你对Android的排期是比较了解的,但是iOS端、FE端、Server端的排期怎么办呢?聪明的你立即把任务派发下去了,给每个端的负责人说,明天中午之前把排期汇总给我。
没错,在多样式列表的设计中也可以采用这种策略,给RecyclerView设置的Adapter不做具体的处理,而是由它派发出去。
实现方案
addDelegate 向Adapter中注册委托Adapter;
addDataList 设置数据;
layout 渲染布局,Adapter查找到对应的委托Adapter,由委托Adapter去做具体渲染。
引入
androidX
implementation 'com.kevin:delegationadapter:2.0.0' // 扩展库,扩展支持了item click、item long click、databinding、load more implementation 'com.kevin:delegationadapter-extras:2.0.0'
support
implementation 'com.kevin:delegationadapter:1.1.8' // 扩展库,扩展支持了item click、item long click、databinding、load more implementation 'com.kevin:delegationadapter-extras:1.1.8'
如何使用
简单用法
带RecyclerView的布局
<?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.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
初始化RecyclerView
Adapter为DelegationAdapter,然后向DelegationAdapter中注册委托Adapter。
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); RecyclerView recyclerView = findViewById(R.id.recycler_view); // ① 设置 LayoutManager // LinearLayoutManager layoutManager = new LinearLayoutManager(this); GridLayoutManager layoutManager = new GridLayoutManager(this, 3); recyclerView.setLayoutManager(layoutManager); // ② 创建 DelegationAdapter 对象 DelegationAdapter delegationAdapter = new DelegationAdapter(); // ③ 向Adapter中注册委托Adapter delegationAdapter.addDelegate(new CompanyAdapterDelegate()); // ④ 设置Adapter recyclerView.setAdapter(delegationAdapter); }
委托Adapter编写
委托Adapter继承自AdapterDelegate,需要两个泛型,第一个为该委托Adapter可处理数据的数据类型(这里为String),第二个参数为ViewHolder。剩下的就按照之前怎么写Adapter来写委托Adapter就可以啦。比如:在onCreateViewHolder创建ViewHolder,在onBindViewHolder中绑定数据到视图控件。
public class CompanyAdapterDelegate extends AdapterDelegate<String, CompanyAdapterDelegate.ViewHolder> { @Override public ViewHolder onCreateViewHolder(ViewGroup parent) { View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false); ViewHolder holder = new ViewHolder(view); return holder; } @Override public void onBindViewHolder(final ViewHolder holder, final int position, final String item) { holder.tvName.setText(item); } static class ViewHolder extends RecyclerView.ViewHolder { public TextView tvName; public ViewHolder(View itemView) { super(itemView); tvName = itemView.findViewById(android.R.id.text1); } } }
设置数据
protected void onCreate(Bundle savedInstanceState) { // ... ... List<String> companies = new ArrayList<>(); companies.add("???????? Baidu"); companies.add("???????? Alibaba"); companies.add("???????? Tencent"); companies.add("???????? Google"); companies.add("???????? Facebook"); companies.add("???????? Microsoft"); // ⑤ 设置数据 delegationAdapter.setDataItems(companies); }
复杂用法
如果想区分????????公司为红色,美国公司为蓝色,怎么办呢?
编写CNCompanyAdapterDelegate
public class CNCompanyAdapterDelegate extends AdapterDelegate<String, CNCompanyAdapterDelegate.ViewHolder> { @Override public boolean isForViewType(String item, int position) { return item.contains("????????"); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent) { View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false); ViewHolder holder = new ViewHolder(view); return holder; } @Override public void onBindViewHolder(final ViewHolder holder, final int position, final String item) { holder.tvName.setText(item); holder.tvName.setTextColor(Color.RED); } static class ViewHolder extends RecyclerView.ViewHolder { public TextView tvName; public ViewHolder(View itemView) { super(itemView); tvName = itemView.findViewById(android.R.id.text1); } } }
编写USCompanyAdapterDelegate
public class USCompanyAdapterDelegate extends AdapterDelegate<String, USCompanyAdapterDelegate.ViewHolder> { @Override public boolean isForViewType(String item, int position) { return item.contains("????????"); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent) { View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false); ViewHolder holder = new ViewHolder(view); return holder; } @Override public void onBindViewHolder(final ViewHolder holder, final int position, final String item) { holder.tvName.setText(item); holder.tvName.setTextColor(Color.BLUE); } static class ViewHolder extends RecyclerView.ViewHolder { public TextView tvName; public ViewHolder(View itemView) { super(itemView); tvName = itemView.findViewById(android.R.id.text1); } } }
注册委托Adapter
// 向Adapter中注册委托Adapter delegationAdapter.addDelegate(new CNCompanyAdapterDelegate()); delegationAdapter.addDelegate(new USCompanyAdapterDelegate());
更多请看示例
THANKS TO
MultiItem 委托思想来源
AdapterDelegates 委托架子来源