Android 复杂的多类型列表视图新写法:MultiType
hehelaa
8年前
<h2>MultiType</h2> <p>Android 复杂的多类型列表视图新写法,清晰、灵活、模块开发、插件化思想</p> <p>这几天晚上回家开始设计我的 TimeMachine 的消息池系统,并抽取出来开源成一个全新的类库: MultiType! 从前,我们写一个复杂的、多 item view types 的列表视图,经常要做一堆繁琐的工作,而且不小心的话代码还堆积严重:我们需要覆写 RecyclerView.Adapter 的 getItemViewType 方法,并新增一些 type 整形常量,而且 ViewHolder 继承、泛型传递、转型也比较糟糕,毕竟 Adapter 只能接受一个泛型……十分麻烦导致过于复杂的页面经常会使用 ScrollView 来实现,一次性加载,而且失去了复用性。</p> <p>而且,一旦我们需要新增一些新的 item view types ,就得去修改 Adapter 旧的代码,步骤繁多,侵入较强。</p> <p>现在好了,只要三步,不需要修改旧代码,只要无脑往池子里插入新的 type ,会自动连接、分发数据和事件,新增再多的 item types 都能轻松搞定,支持 RV 、复用,代码模块开发,清晰而灵活。若要说为什么这么灵活? 因为它本来就是为 IM 视图开发的,想想 IM 的消息类型可能有多少种而且新增频繁。</p> <h2>接入</h2> <p>在你的 build.gradle :</p> <pre> <code class="language-java">dependencies { compile 'me.drakeet.multitype:multitype:1.1-beta2' }</code></pre> <h2>使用</h2> <p>Step 1. 创建一个 classimplements ItemContent ,它将是你的数据类型或 Java bean ,示例:</p> <pre> <code class="language-java">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(); } }</code></pre> <p>Step 2. 创建一个 class 继承 ItemViewProvider<T extends ItemContent> ,示例:</p> <pre> <code class="language-java">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); } }</code></pre> <p>Step 3. 好了,你不必再创建新的类文件了,只要往你的 Activity 中加入 RecyclerView 和 List<TypeItem> 即可,示例:</p> <pre> <code class="language-java">@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)); }</code></pre> <p>大功告成!</p> <p>你可以阅读源码项目中的 sample 模块获得更多信息和示例,当完整的示例代码运行起来,它是这样子的:</p> <p><img src="https://simg.open-open.com/show/e866692679e4455c55efd6baf5013bd2.jpg"></p> <h2>题外话</h2> <p>这个类库成品看来是挺精巧的,或者说轻巧,但一个人从无到有把它设计和创造出来,还是费了很多思考和多次推翻重构,其中有些点看起来可能自然而然,但是它在开发过程中可能都是一个小坎,如果没有找到合适的结构或设计,整体可能就不能搭建起来,使用也可能没那么简单和灵活。所以,要是有人感兴趣,之后可以分享一下开发过程中遇到的问题和思考,还是很有意思的 : )</p> <p> </p> <p>来自:https://drakeet.me/multitype</p> <p> </p>