Android 复杂的多类型列表视图新写法:MultiType

MultiType

Android 复杂的多类型列表视图新写法,清晰、灵活、模块开发、插件化思想

License maven-central

中文版 | 英文版(English Version)

GitHub: https://github.com/drakeet/MultiType

这几天晚上回家开始设计我的 TimeMachine 的消息池系统,并抽取出来开源成一个全新的类库: MultiType! 从前,我们写一个复杂的、多 item view types 的列表视图,经常要做一堆繁琐的工作,而且不小心的话代码还堆积严重:我们需要覆写 RecyclerView.AdaptergetItemViewType 方法,并新增一些 type 整形常量,而且 ViewHolder 继承、泛型传递、转型也比较糟糕,毕竟 Adapter 只能接受一个泛型……十分麻烦导致过于复杂的页面经常会使用 ScrollView 来实现,一次性加载,而且失去了复用性。

一旦我们需要新增一些新的 item view types ,就得去修改 Adapter 旧的代码,步骤繁多,侵入较强

现在好了,只要三步,不需要修改旧代码,只要无脑往池子里插入新的 type ,会自动连接、分发数据和事件,新增再多的 item types 都能轻松搞定,支持 RV 、复用,代码模块开发,清晰而灵活。若要说为什么这么灵活? 因为它本来就是为 IM 视图开发的,想想 IM 的消息类型可能有多少种而且新增频繁。
继续阅读

当我们谈 XML 布局文件代码的优雅性

当我们谈代码的优雅性,是不可以忽略经常在打交道的 Android XML 布局文件的书写。有人会问,XML 文件内容有什么优雅不优雅的,不都是随便写吗?嗯,是有很多人,根本就没有意识到或者不关心布局文件内容应该怎么写更好看,更漂亮。我觉得,优雅的 Android XML 布局文件的内容,应该做到以下几点:

  • 不能有多余的空行;
  • 不要保留你注释掉的代码(要回溯我们有 git);
  • 尽量避免 hard code(硬编码);
  • 能复用的资源尽量抽出到对应的 value 文件;
  • 尽量消除警告、单词拼写错误;
  • 不要使用废弃的关键词,如 fill_parent、dip;
  • 属性条目要有序;

其中,本文特别想讲的就是最后一条,“属性条目要有序”,属性条目指的是,比如一个 ImageView 节点下的 android:id, android:layout_width, android:paddingLeft, android:src … 等等这些。大部分人在书写 Android XML 布局文件的时候,都是想到一个要设置的属性,就随意在原有的属性们之下一行,再加上一行新属性,这样导致诸如 android:id 有时会在最后一行,有时在一堆属性中间,不仅不利于我们在需要 id 的时候,肉眼查找阅读,也会使得整个 XML 文件内容没有规则,很凌乱。

继续阅读

使用 MailOtto 做预加载

最近我开源了一个专注懒事件的事件总线 MailOtto: https://github.com/drakeet/MailOtto 并写了一个用它来做预加载的实践案例:第一个页面预先为第四个页面发起数据加载请求,等用户进入第四个页面,那加载好的数据才会分发给它,若在数据下来前进入第四个页面,也会等完成的时候自动接收到。

这个数据需要 8 秒,如果进入到第四个页面才开始加载,体验就很不好,就算只要 1 秒,也会有一个文本从无到有闪动的过程。如果在第一个页面停留超过 8 秒,它足够完成全程预加载,进入第四个页面里面就能直接拿到数据,可谓完美预加载。

本文就是来介绍一下这个实践案例。
继续阅读

Android 内存泄漏案例和解析

Android 编程所使用的 Java 是一门使用垃圾收集器(GC, garbage collection)来自动管理内存的语言,它使得我们不再需要手动调用代码来进行内存回收。那么它是如何判断的呢?简单说,如果一个对象,从它的根节点开始不可达的话,那么这个对象就是没有引用的了,是会被垃圾收集器回收的,其中,所谓的 “根节点” 往往是一个线程,比如主线程。因此,如果一个对象从它的根节点开始是可达的有引用的,但实际上它已经没有再使用了,是无用的,这样的对象就是内存泄漏的对象,它会在内存中占据我们应用程序原本就不是很多的内存,导致程序变慢,甚至内存溢出(OOM)程序崩溃。

内存泄漏的原因并不难理解,但仅管知道它的存在,往往我们还是会不知觉中写出致使内存泄漏的代码。在 Android 编程中,也是有许多情景容易导致内存泄漏,以下将一一列举一些我所知道的内存泄漏案例,从这些例子中应该能更加直观了解怎么导致了内存泄漏,从而在编程过程中去避免。
继续阅读

浅谈 Android 编程思想和架构

我主要是想讲一讲自己对于 接口、模块化、MVP 的一些心得。

有这么一个场景,两个不同的页面,包含了看起来一模一样的界面内容(或者称 frame/UI),这种场景可能很常见,有时看到会说:“哈哈,我可以设计个复用!” 但是遇到一个问题是,这两个页面需要分别去请求不同的服务端 API,返回下来的数据结构也不一样(姑且不说去和服务端开发协商),这样就会导致具体的 view holder 或者适配器在绑定数据的时候无法复用,为何说无法复用或难以复用呢?举个例子,比如传进 Apdapter 的 list item 数据内容不一样,你总不能把 item 再拆了,分好几个 list 传进去吧?面向具体编程情况下,适配器得到不同的 items,得对 item 分发数据绑定到 UI,难免要写很多重复的代码。

这时候我们可以采取面向抽象编程,既然不同的数据对应一样的 UI,如果它们都实现了一样的接口,这个接口的设计取决于 UI 需要哪些数据块,然后不同的 Item model 去实现这个接口提供数据即可,这时适配器只要持有这个接口类型的 Item 即可,举个通俗的例子:数据模型1和2都实现了 IPost 接口,那么适配器就只要持有 List<IPost> 数据即可,List<数据模型1> 和 List<数据模型2> 都可以视作“一样的鸭子”传递给这个适配器。这样把数据模型的数据块抽取放到了数据模型本身实现,不仅不用写很多重复的分发代码,而且适配器本身都能复用了;当接口需要新的方法,也能驱动着实现者们去实现。
继续阅读

Retrofit 2.0 + OkHttp 3.0 配置

Retrofit 和 OkHttp 都是伟大的 Square 公司开源的伟大项目。前段时间也是从 Retrofit 1.9 升级到 2.0 beta 4 版本,从 OkHttp 2.+ 版本升级到  3.0.1 版本。这两者在各自的这两个大版本升级中,都改变了不少,使得原本的代码都需要进行一些修改才能使用,我也是稍微摸索了几下,如今大致摸清,把一些基础配置,比如设置 Json 转换器、RxJava 适配器、设置 Debug Log 模式、设置超时、错误重连,以及配置 Access token Interceptor 等等一些内容,分享一下。
继续阅读

一种新的 Header View + RecyclerView 实现方式

在 GitHub 开源了一种新的 Header View + RecyclerView 实现方式,使用 CoordinatorLayout 把 header 抽离出 RecyclerView,并做到上下滑联动,这样 Java 层代码就能简单和简洁很多,更便于刷新和响应,也不用写多 item view type 逻辑。

源代码:

https://github.com/drakeet/RecyclerViewWithHeaderNewPractice

XML 代码层次是这样的:

说明:

  • 可以使用 SmoothAppBarLayout 这个第三方库,它是一个提供顺滑滚动的 AppBarLayout 补足库,这一个层次必须置于 RecyclerView 代码下面,也就是界面上是在 RecyclerView 的上层,这样AppBarLayout 包裹的 header views 才能接收到点击事件(其实根本原因是,RV 对于 Padding 部分也会拦截手势所以不得不这么做)。
  • 如果想要列表上滑的时候,状态栏跟随着滑动显示出阴影效果,可以在 FrameLayout 外再包裹一层 android.support.design.widget.CollapsingToolbarLayout. 可以实现如图效果(注意状态栏阴影):
  • Demo 中的 UI 来自著名的 App Peach,为了避免写太多无关的、具有干扰性的 UI 代码,俺使用了两部分截图来替代繁琐的 UI 实现,在此声明和感谢  Peach.

使用 Python 创建 Telegram 机器人

要说聊天体验,telegram 比微信好很多,微信消息一多就卡,而且没法直接引用消息进行回复导致经常找不到上下文。telegram 则始终异常流畅,记录阅读位置,消息多的时候也不会觉得跟不上聊天节奏或卡 … 当然了,这一段都不是今天要写的这篇文章的重点,这篇文章主要还是要介绍一下如何开发 telegram 机器人,telegram 在去年中旬的时候开放了机器人的 API,可以设置 hook,使得所有消息都能被转发到你的服务上,然后作出自动化回复。

机器人可以被邀请入群做很多辅助工作,比如输入 “/google xxx” 就可以得到谷歌查询的结果等等,甚至还有人开发了 /fff 命令,用来烧死异性恋😂什么的,只要发送一条 “/fff install someone” 的消息到机器人所在的群聊当中即可。总之,利用 bot API 几乎无所不能,也十分有意思。

俺从几天前开始玩耍 telegram bot API,开发了一个属于自己的机器人,@XiaoaiBot,可以回声、计算两个日期的间隔时间、以及帮用户在群里找出最近一个 @ 消息,应该说还是非常好玩的。
继续阅读

2016.2.19 再见

哎 … 春节放假结束了。原本是17号晚上要坐动车回厦门的,结果突然想到忘记见福贵一面了,若是不见可能又要等到一年后,于是改签到今天。

时间过得很快,阿贵也很快就走了。只记得他说我很好看,我也觉得他很好看,然后再见了,我很怀念他 …

那天晚上晓忆请我去看了火影忍者博人传的电影,其实就是昨天晚上,觉得很好,仿佛又一次看到了吊车尾的鸣人成长记,十分感动。原本是打算回来的时候写一篇日记的,结果回来之后又忍不住想写代码,而且觉得应该一会儿就搞定 便可以写日记,结果直到睡觉的时候才完成,日记也就变成今天写了。 继续阅读

2016.2.6 “生活总是一步一步往前走,岁月也一去不回头。”

最近在 twitter 看到一句话转推了,甚是感慨。说……额,还是不说为好,哈哈哈。

今天参加了高中同学的大四期聚会,还是很高兴的。大学上了两年就出来工作,对我而言已经没有毕业没有大学了。而如今怀念在意的大家都快毕业了,听说又有聚会,才确定了回家时间,3号定的动车票,4号回来。之前几年,还是经常装各种理由不去的,虽然自己一点都没有变,大家也都没有变,只是很多都暂时生疏了;虽然我还是默默一个人,另外也有一些遗憾,但总的来说还是非常高兴能够看到大家的。

吃了饭,似乎是分成了两批人,暂且说一批是桌游派,一批是照相派,哦对了,还有女生的去向不明派。我们8个人一起去玩了桌游,泽涵,杰龙,晓忆,柏年,林彧,文雄,黄鑫,还有我。也是因此导致了俺没有出现在后来的留影中——或许是好事,哈哈。玩了晓忆带过来的 “Avalon” 游戏,类似杀人游戏或狼人杀那样的角色扮演、逻辑推理桌游,但比较起来好玩多了,规则简单,但每个人都能一直参与、很有意思(或许是因为和大家一起?),然后… 很难,好在玩了几局大家都挺快上手的,时间也是过得很快,最后分别,我和晓忆一起沿着世纪大道走回家,小时候是觉得这条路是非常长,如今发现没一会儿就走到了达利园酒店,再没一会儿就到体育馆路口了,真神奇。

回想这些年,稍纵即逝,高中那些情绪、冲动,日思梦想,以及和福贵在一起的美好幸运的时光,仿佛就在昨天:下课了阿贵很快跑来和我说话,傍晚的时候还能在走廊里望着楼下发发呆(看喜欢的人来了没有😂),再也回不去了,甚是惆怅。到了大学,很可惜没有留下什么回忆,可能的记忆,就是还有一些喜欢的朋友,和宿舍伙伴,还有那些每次我回来,就从别的宿舍窜过来和我打招呼的好朋友;记得和谁谁一起去过鼓浪屿,一起去看诸如小时代的电影,等等这些,再多就是大学里走的路,或许多年后也会比较感慨。思琦给我写过一段大学感慨,我觉得完全是俺的总结,甚是感人😂,贴于此:

“生活总是一步一步往前走,岁月也一去不回头。”