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>