围绕Android平台,分享手机开发经验的精彩文章数不胜数,但针对TV的技术文章远不及手机,优秀的分享就更屈指可数。本篇文章以QQ音乐Android TV版研发过程举例,深度研究Leanback,剖析其优劣,称得上是一篇不错的技术总结,相信读者将从中获益。 责任编辑:harveyxu
Leanback是Google在2014年11月添加到Support Library系列中专用于Android TV开发的依赖库。按照Google官方文档中的说法,Android TV和Leanback都是为了让用户能够有一个理想的三米距离电视观看体验(10-foot Experience)而诞生的。
Leanback库对于TV App开发者而言最大的帮助在我看来有两点:
简介就到这里,优劣之处大家见仁见智,下面我们开始正文部分
通过在build.gradle文件中添加如下语句即可引入最新的Leanback库:
implementation androidx.leanback:leanback:1.1.0-alpha02
然而由于Leanback的维护频率略微有些堪忧,因此在使用过程当中可能会发现一些和项目本身技术方案不匹配的地方(如 Leanback要求minSDK >= 17, etc.),在这种情况下推荐使用源码接入方式引入Leanback库。
在从宏观来看,Leanback非常适合使用MVP开发架构。在我们的实践中发现Leanback对于View和Presenter的开发有很大的帮助,在很多开发场景当中,只需要实现model即可完成页面开发,非常便捷。在本节当中会讲解Leanback的核心组件和使用思路。
GridView系列是Leanback库UI布局的核心组件。从上图(转自CSDN)可以看出,基类BaseGridView继承自RecyclerView, 重写了关于焦点处理的大量方法,配合GridLayoutManager实现了包括焦点记忆、视图滚动对齐策略等功能。开发者在使用的过程当中几乎只需要关注数据填充部分功能的实现即可,极为方便。Leanback中提供了两个BaseGridView的子类供大家使用,VerticalGridView和HorizontalGridView。通过组合这两个组件可以实现非常丰富的布局格式。如下图就是一个例子,根布局下为一个VerticalGridView,子布局是多个HorizontalGridView。当然如果不想套用GridView的话,也可以通过setColumnNum方法来实现Grid布局。
3.2 数据填充
原先在我们使用RecyclerView/ListView时,只需要实现对应的Adapter接口即可。然而在Leanback当中对Adapter结构进行了优化,对数据展示逻辑进行了解耦。在RecyclerView.Adapter当中我们通过viewType来配合onCreateViewHolder来进行不同类型的ViewHolder的创建。这一逻辑存在两个潜在的问题:
在Leanback当中,这一逻辑被解耦成四个组件:
需要关注的类变多了,但其实逻辑非常清晰。Presenter和PresenterSelector共同负责原先Adapter中关于ViewHolder的处理逻辑。Presenter的实现较为简单,如UML图所示,主要负责ViewHolder的创建和数据绑定/解绑。onCreate/Bind/UnbindViewholder方法的实现方式和以往完全相同。
而PresenterSelector则承担了之前viewType相关的功能,根据数据的类型来调用不同的Presenter进行ViewHolder的创建。只需要根据传入的item参数来生成对应的Presenter。这里返回的Presenter会被用在ObjectAdapter中用于创建ViewHolder。
ItemBridgeAdapter和ObjectAdapter用于连接Presenter/PresenterSelector和RecyclerView。Leanback中已经提供了部分实现好的子类,如ArrayObjectAdapter、ListRowAdapter、CursorObjectAdapter和SparseArrayObjectAdapter,涵盖了大量的开发场景。当然如果有需要的话也可以自己继承实现。
在我们一个大版本的开发过程当中,Leanback库充分展示出了其强大的辅助开发能力。使得我们在很短的时间内就完成了UI框架的搭建。但是不得不说这个库确实也存在着一些难以忽视的缺点:不够成熟。相比其他的support库来说,这个库无论是从更新频率还是完成度上都稍有不足:比如经常有莫名其妙的仅限Library Group访问的变量和方法;内部接入的RecyclerView版本较低,存在着历史遗留问题无法解决等。因此最终我们也不得不采用源码接入的方式来引入Leanback。不过只要把坑都踩清楚了,用起来还是很香的!本篇中只讲了较为基础的Leanback使用,后续会努力再写一篇教大家如何进行组件定制化的文章,请大家多多期待~
5. 参考
Leanback库:
https://developer.android.com/jetpack/androidx/releases/leanback
Leanback Demo Github地址:https://github.com/android/tv-samples
Leanback Codelab教程地址:https://codelabs.developers.google.com/codelabs/androidtv-adding-leanback/index.html#0