搞笑
activitythread(开源 - Scene:Android 开源页面导航和组合框架)

Scene 最初用于解决西瓜视频的直播业务在演进过程中遇到的问题,后来又在抖音的拍摄工具中落地,经过了实践与验证,于是团队觉得将其开源到社区,希望能够帮助大家在更多的场景解决问题。

西瓜视频面临的问题

下面的视频是老版本的过度效果:

这种复杂的过渡动画,是不可能拿 Activity 实现的。然而 Fragment 在那个时候也会出现各种怪异的状态保存引发的崩溃(虽然知道崩溃的原理,但是不能接受这种设计),于是西瓜视频技术团队设计了名为 Page 的 UI 方案,来实现过渡动画这个需求。

下面是西瓜长视频详情页和抖音拍摄页面使用Scene的场景截图:

西瓜的长视频页面和抖音的拍摄页面截图

这里简单列下 Activity 和 Support 28 的 Fragment 的不足,部分问题已经在 Android X 的 Fragment 上修复了。

页面组合对比 Fragment

  1. 各种奇怪的崩溃,就算不用 Fragment,但是用了 AppCompatActivity 还是会在 onBackPressed 里面触发崩溃;

功能特点

基本概念

Scene

GroupScene

Scene 使用

这里介绍简单的上手,更多用法见 Github 仓库的示例。

添加依赖:

创建 Activity:

运行就可以了。

导航

返回:

设置结果:

组合的 API 类似 Fragment,继承 GroupScene,然后可以操作任意 Scene 添加到自己的 View 布局内:

通讯

Scene 支持 ViewModel,可以通过 by activityViewModels,by viewModels 拿到托管到 Activity 或者自己的 ViewModel:

动画

在 Push 的时候,通过 PushOptions 可以配置简单的过场动画:

右划返回

核心设计思路

  1. Scene 本身是在 View 上面包一层生命周期,通过一个叫 LifeCycleFragment 的原生 Fragment 分发生命周期事件给框架内部,再由父组件同步给子组件。
  2. 父子组件同步生命周期,在原则上: 进入的时候,先执行父组件的生命周期回调,再执行子组件的生命周期回调; 退出的时候,先执行子组件的生命周期回调,再执行父组件的生命周期回调;
  3. NavigationScene 负责导航栈的处理,GroupScene 负责页面组合的处理,有点类似 iOS 的 UINavigationController/UIViewController,WinRT 的 Page。拆分的原因,是出于考虑性能,因为导航这个任务,由于动画的要求,本身的层级就会比普通的页面组合复杂,动画的 API 也更加强大。这两件事情,本身影响的生命周期也不一样,导航会影响之前的页面,而组合并不会。
  4. 生命周期和动画的处理原则是,先执行完生命周期,然后拿前后两个页面的 View 做动画,所以避免了Activity 动画需要在页面之间来回传递 Bitmap 来模拟控件这种繁琐的步骤,也避免了 Activity 动画黑屏的问题。
  5. 最后再由于 Transition 库过于无力,所以用系统核心的 GhostView,Scene 重头实现一遍共享元素动画。

未来与总结

Scene Dialog,开发中,用于解决 Android 框架的 Dialog 因为是基于 Window 会盖在普通的 View 之上的问题。

基于 View 重新实现的导航和组合方案,一方面是没有之前的技术债,一方面可以跳出 Google 的想法,比如说可以控制状态保存的范围,来实现更加强大的动画能力和组件通讯能力,这是官方的组件不会提供给开发者的。

Single Activity: Why, When, and How (Android Dev Summit '18)(https://www.youtube.com/watch?v=2k8x8V77CrU)

Conductor (https://github.com/bluelinelabs/Conductor)


欢迎关注「字节跳动技术团队」


顶一下()     踩一下()

热门推荐

发表评论
0评