什么是 Leanback Library?它提供了哪些核心组件?

解读

在国内 Android-TV/OTT 面试中,Leanback 是区分“只会手机开发”和“真正做过电视大屏”的分水岭。面试官问这道题,通常想确认三件事:

  1. 你是否知道 TV 与手机在交互范式(遥控器 vs 触屏)、屏幕密度(2 m 视距 vs 30 cm)、焦点逻辑(D-pad)上的根本差异;
  2. 你是否真的用过 Google 官方提供的 Leanback Support Library(现迁移至 androidx.leanback),而不是自己用 RecyclerView 拼“假 TV 界面”;
  3. 你能否把“组件名称 → 作用 → 典型场景”一口气讲清楚,证明你阅读过源码或至少写过 Demo。

回答时切忌只背类名,要把“为什么需要这个组件”讲透,再给出国内适配的坑(如焦点错乱、中文输入法键码、小米/海信遥控器兼容)。

知识点

  1. Leanback 定位:Google 在 2014 年随 Android 5.0 推出的 TV 专用 Support-Library,后整体迁入 androidx.leanback:1.2.x,与 androidx.tv 并行迭代;它基于 Fragment 实现,屏蔽 D-pad 焦点算法、渐变背景、十字轴焦点搜索,让开发者专注业务。
  2. 核心架构:Presenter → 数据与视图绑定;ObjectAdapter → 数据层;Row/RowPresenter → 行容器;Fragment → 场景化页面;BackgroundManager → 全屏渐变背景;SearchFragment → 语音/键盘双入口搜索。
  3. 焦点机制:Leanback 内部重写了 FocusHighlightHelper,在 RecyclerView 之上封装 ListRowPresenter,自动处理“边缘回弹、圆形边缘、焦点放大 1.1 倍”的动画;国内盒子若出现焦点飞走,需重写 BrowseFragment 的 setOnKeyListener 并屏蔽某些厂商的键码 268~285。
  4. 国内兼容:华为鸿蒙盒子对 KeyEvent.KEYCODE_DPAD_CENTER 响应延迟 80 ms,需用 KeyEvent.KEYCODE_ENTER 兜底;小米电视 6 系列在 1080P 60 Hz 下会强制关闭 32-bit surface,导致 Leanback 的 DetailsOverviewRow 阴影带锯齿,需强制 RGBA_8888。
  5. 版本演进:2023 I/O 后 Google 主推 androidx.tv(Compose for TV),但国内存量终端 80% 仍跑 API 28~30,Leanback 仍是面试与量产主流;官方承诺维护到 2026 年,因此“Leanback 过时论”在国内不成立。

答案

Leanback Library 是 Google 官方面向 Android-TV 的专属 UI 框架,位于 androidx.leanback,目标是让开发者用“行模型”快速搭建遥控器驱动的十英尺界面。它屏蔽了 D-pad 焦点算法、十字轴搜索与背景渐变细节,使业务层只需声明“数据 + Presenter”即可。

核心组件可拆成“六大件 + 三辅助”:

  1. BrowseSupportFragment
    首页标准模板,顶部有 HeadersFragment(左侧导航)与 RowsSupportFragment(右侧内容行),内置焦点守卫、边缘回弹、背景渐变;通过 setBrandColor 可植入厂商品牌色,国内项目常重写 onCreateTitleView 插入 IPTV 牌照号。

  2. DetailsSupportFragment
    详情页模板,顶部是 DetailsOverviewRow(视频海报、评分、导演信息),底部有 ListRow(相关推荐);支持“预览窗口”在 5 s 无操作后自动播放片花,国内爱优腾会替换为 ExoPlayer + 码率自适应。

  3. RowsSupportFragment + ListRowPresenter
    行容器与行渲染器,一行对应一个 HorizontalGridView,焦点在左右滑动时自动放大 1.1 倍;每行可混排多种 Presenter,实现“标题 + 海报 + 按钮”的异构布局,是首页最常用组合。

  4. Presenter + ObjectAdapter
    MVP 数据绑定层,Presenter 负责把数据对象转成 ViewHolder,ObjectAdapter 负责维护列表;与 RecyclerView.Adapter 不同,Leanback 的 Presenter 可跨行复用,实现“横竖混排”。

  5. SearchSupportFragment
    全局搜索入口,已集成语音输入(RecognizerIntent),并适配国内遥控器 T9 键盘;通过 setSearchQueryProvider 可对接自家搜索引擎,返回的 ObjectAdapter 直接塞进 RowsSupportFragment 实现“边输入边出结果”。

  6. GuidedStepSupportFragment
    向导式弹窗,把“多步设置”拆成左侧列表 + 右侧描述,支持单选、复选、文本输入;国内运营商常用它做“首次开机激活 + 宽带账号输入”,可屏蔽返回键防止用户跳过。

辅助组件:

  • BackgroundManager:在 Fragment 切换时做 250 ms 的交叉渐变,支持本地 drawable 与网络 URL 双源,国内项目会接入 CDN 高斯模糊图减少 60% 带宽。
  • TitleView:可插入动态 Logo、天气、时间,支持 RTL 布局,海外盒子必备。
  • VerticalGridSupportFragment:用于展示“网格海报”场景,如综艺合集,焦点纵向移动时自动对齐行首。

一句话总结:Leanback 把 TV 首页、详情页、搜索页、设置页做成了“填空题”,开发者只需写 Presenter 与数据,就能在 1 天内跑出符合国内合规要求的 OTT Launcher。

拓展思考

  1. 国内“双牌照”监管要求 Launcher 首页必须露出 CCTV-1 直播入口,而 Leanback 的 HeadersFragment 默认只能显示 3~5 个 tab,如何在不改源码的情况下动态插入“直播”行且保证焦点优先级最高?
    提示:重写 BrowseSupportFragment 的 createMainFragmentAdapter,在 onBind 阶段把直播行插入 position=0,并设置 setSelectedPosition(0, false) 抢占焦点;同时用 setHeaderPresenterSelector 为直播行返回一个带红色图标的自定义 Presenter,满足合规醒目要求。

  2. 当 androidx.tv(Compose for TV)正式 GA 后,存量 Leanback 代码如何低成本迁移?
    思路:利用 Compose 的 AndroidView 把 BrowseSupportFragment 整体嵌入 Compose 布局,先迁详情页与搜索页到 Compose,首页仍保留 Leanback;通过共享 ViewModel 实现双向数据同步,逐步替换 Presenter 为 Compose UI,最终把 RowsSupportFragment 换成 TvLazyRow。国内项目可先在 A/B 灰度通道验证焦点稳定性,再全量切换。

  3. 焦点抖动与键码冲突是电视端面试高频追问:

    • 若用户反馈“按一下遥控器方向键,焦点飞两行”,应如何定位?
      答:先用 adb shell input keyevent 复现,抓 Systrace 看 KeyEvent 分发间隔;若两次 KeyEvent 间隔 < 80 ms,可判定厂商驱动重复上报,需在 Activity 的 dispatchKeyEvent 里做 100 ms 防抖。
    • 若 KeyEvent.KEYCODE_DPAD_CENTER 在某些盒子无效,但手机虚拟遥控器有效,如何处理?
      答:国内盒子把 OK 键映射成 KEYCODE_ENTER,兜底方案同时监听 KEYCODE_DPAD_CENTER 与 KEYCODE_ENTER,并消费事件防止冒泡。