一种优雅的方式来使用RecyclerView
使得RecyclerView各种情况的多类型条目更简单!
示例图片
下载体验
核心思想
想必大家都遇到过,在一个列表中显示不同样式的需求。在RecyclerView中可以通过ViewType进行区分,如果样式特别多的时候就会使得代码非常冗余,不利于开发及维护。那么有没有一种优雅的方法解决这个问题呢?
技术经理给你说,接下来的项目由你负责,明天下班前把排期同步出来。这时你应该怎么做?由于你是Android端的RD,你对Android的排期是比较了解的,但是iOS端、FE端、Server端的排期怎么办呢?聪明的你立即把任务派发下去了,给每个端的负责人说,明天中午之前把排期汇总给我。
没错,在多样式列表的设计中也可以采用这种策略,给RecyclerView设置的Adapter不做具体的处理,而是由它派发出去。
实现方案
- addDelegate 向Adapter中注册委托Adapter;
- addDataList 设置数据;
- layout 渲染布局,Adapter查找到对应的委托Adapter,由委托Adapter去做具体渲染。
引入
androidX
implementation 'com.zwenkai:delegationadapter:2.0.8'
// 扩展库,扩展支持了item click、item long click、databinding、load more
implementation 'com.zwenkai:delegationadapter-extras:2.0.8'
support[不在支持]
// JCenter
implementation 'com.kevin:delegationadapter:1.2.1'
// 扩展库,扩展支持了item click、item long click、databinding、load more
implementation 'com.kevin:delegationadapter-extras:1.2.1'
如何使用
简单用法
-
带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 委托架子来源