Android 复杂的多类型列表视图新写法,清晰、灵活、模块开发、插件化思想
中文版 | 英文版 (English Version)
GitHub: https://github.com/drakeet/MultiType
这几天晚上回家开始设计我的 TimeMachine 的消息池系统,并抽取出来开源成一个全新的类库: MultiType! 从前,我们写一个复杂的、多 item view types 的列表视图,经常要做一堆繁琐的工作,而且不小心的话代码还堆积严重:我们需要覆写 RecyclerView.Adapter
的 getItemViewType
方法,并新增一些 type 整形常量,而且 ViewHolder
继承、泛型传递、转型也比较糟糕,毕竟 Adapter
只能接受一个泛型……十分麻烦导致过于复杂的页面经常会使用 ScrollView 来实现,一次性加载,而且失去了复用性。
现在好了,只要三步,不需要修改旧代码,只要无脑往池子里插入新的 type ,会自动连接、分发数据和事件,新增再多的 item types 都能轻松搞定,支持 RV 、复用,代码模块开发,清晰而灵活。若要说为什么这么灵活? 因为它本来就是为 IM 视图开发的,想想 IM 的消息类型可能有多少种而且新增频繁。
在你的 build.gradle
:
dependencies { compile 'me.drakeet.multitype:multitype:1.1-beta2' }
ItemContent
,它将是你的数据类型或 Java bean
,示例: public class TextItemContent implements ItemContent, Savable { @NonNull public String text; public TextItemContent(@NonNull String text) { this.text = text; } public TextItemContent(@NonNull byte[] data) { init(data); } @Override public void init(@NonNull byte[] data) { String json = new String(data); this.text = new Gson().fromJson(json, TextItemContent.class).text; } @NonNull @Override public byte[] toBytes() { return new Gson().toJson(this).getBytes(); } }
ItemViewProvider<T extends ItemContent>
,示例: public class TextItemViewProvider extends ItemViewProvider<TextItemContent> { private static class ViewHolder extends ItemViewProvider.ViewHolder { @NonNull final TextView text; ViewHolder(@NonNull View itemView) { super(itemView); this.text = (TextView) itemView.findViewById(R.id.text); } } @NonNull @Override protected View onCreateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) { View root = inflater.inflate(R.layout.item_text, parent, false); ViewHolder holder = new ViewHolder(root); root.setTag(holder); return root; } @Override protected void onBindView( @NonNull View view, @NonNull TextItemContent content, @NonNull TypeItem typeItem) { ViewHolder holder = (ViewHolder) view.getTag(); holder.text.setText("hello: " + content.text); } }
Activity
中加入 RecyclerView
和 List<TypeItem>
即可,示例: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = (RecyclerView) findViewById(R.id.list); itemFactory = new TypeItemFactory.Builder().build(); TypeItem textItem = itemFactory.newItem(new TextItemContent("world")); TypeItem imageItem = itemFactory.newItem(new ImageItemContent(R.mipmap.ic_launcher)); TypeItem richItem = itemFactory.newItem(new RichItemContent("小艾大人赛高", R.mipmap.avatar)); List<TypeItem> typeItems = new ArrayList<>(80); for (int i = 0; i < 20; i++) { typeItems.add(textItem); typeItems.add(imageItem); typeItems.add(richItem); } /* register the types before setAdapter, that's all right */ ItemTypePool.register(TextItemContent.class, new TextItemViewProvider()); ItemTypePool.register(ImageItemContent.class, new ImageItemViewProvider()); ItemTypePool.register(RichItemContent.class, new RichItemViewProvider()); recyclerView.setAdapter(new TypeItemsAdapter(typeItems)); }
你可以阅读源码项目中的 sample
模块获得更多信息和示例,当完整的示例代码运行起来,它是这样子的:
这个类库成品看来是挺精巧的,或者说轻巧,但一个人从无到有把它设计和创造出来,还是费了很多思考和多次推翻重构,其中有些点看起来可能自然而然,但是它在开发过程中可能都是一个小坎,如果没有找到合适的结构或设计,整体可能就不能搭建起来,使用也可能没那么简单和灵活。所以,要是有人感兴趣,之后可以分享一下开发过程中遇到的问题和思考,还是很有意思的 : )