QQ音乐TV版 Leanback接入实践分享(一)

语言: CN / TW / HK

围绕Android平台,分享手机开发经验的精彩文章数不胜数,但针对TV的技术文章远不及手机,优秀的分享就更屈指可数。本篇文章以QQ音乐Android TV版研发过程举例,深度研究Leanback,剖析其优劣,称得上是一篇不错的技术总结,相信读者将从中获益。

责任编辑:harveyxu

1. Leanback简介

Leanback是Google在2014年11月添加到Support Library系列中专用于Android TV开发的依赖库。按照Google官方文档中的说法,Android TV和Leanback都是为了让用户能够有一个理想的三米距离电视观看体验(10-foot Experience)而诞生的。

Leanback库对于TV App开发者而言最大的帮助在我看来有两点:

  • Leanback提供了以BaseGridView及其子类为核心的一整套开发框架,其中包括

    • Google的TV设计风格

    • 对Adapter机制的优化,添加了Presenter、PresenterSelector等组件,通过套接的方式实现了灵活的布局实现方式和逻辑解耦

    • 继承自RecyclerView的BaseGridView、VerticalGridView、HorizontalGridView;帮助开发者实现了大量关于焦点控制的底层逻辑,有效提升开发效率

    • RowsSupportFragment,BrowseFragment等页面级组件,连布局设计都一手包办。甚至还内置有实现新手教程的Fragment,只需提供新手教程逻辑就可光速上线,简直不能更贴心。

    • 这点实际上是延伸自上一点中的最后一小项。由于Leanback中提供的Fragment级组件,开发者可以获得Google级的设计资源。这一点对于需要快速推进项目或者设计资源比较匮乏的团队来说尤为宝贵。对于比较成熟的开发团队来说这一点的价值就没有那么大,不过依旧可以通过研究为什么Google要这么设计页面来学习TV上的用户使用习惯,这也是十分重要的信息。

简介就到这里,优劣之处大家见仁见智,下面我们开始正文部分

2. 依赖引入

通过在build.gradle文件中添加如下语句即可引入最新的Leanback库:

implementation androidx.leanback:leanback:1.1.0-alpha02

然而由于Leanback的维护频率略微有些堪忧,因此在使用过程当中可能会发现一些和项目本身技术方案不匹配的地方(如 Leanback要求minSDK >= 17, etc.),在这种情况下推荐使用源码接入方式引入Leanback库。

3. 开发框架 & 核心组件

在从宏观来看,Leanback非常适合使用MVP开发架构。在我们的实践中发现Leanback对于View和Presenter的开发有很大的帮助,在很多开发场景当中,只需要实现model即可完成页面开发,非常便捷。在本节当中会讲解Leanback的核心组件和使用思路。

3.1 BaseGridView组件

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的创建。这一逻辑存在两个潜在的问题:

  • 如果ViewHolder的种类较多,Adapter的代码会变得非常臃肿

  • 不同类别的ViewHolder代码复用起来较为麻烦,需要自行进行封装。

在Leanback当中,这一逻辑被解耦成四个组件:

  • Presenter

  • PresenterSelector

  • ObjectAdapter

  • ItemBridgeAdapter

需要关注的类变多了,但其实逻辑非常清晰。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,涵盖了大量的开发场景。当然如果有需要的话也可以自己继承实现。

4. 结语

在我们一个大版本的开发过程当中,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

分享到: