开源 _ Scene:Android 开源页面导航和组合框架

  1. 栈管理弱,Intent+LaunchMode 的设计,使得开发者在使用的时候要么极容易出错,要么用 Hack 做对了但是动画过度黑屏;
  2. Activity 性能差,普通的空白页面切换也得 60、70ms 耗时(基于三星 S9 设备测试);
  3. 因为销毁恢复的强制要求:
  • 导致的 Activity 动画能力非常弱,无法直接拿到前后两个页面的 View 也就无法简单的实现复杂的交互动画;
  • SharedElement 动画能力弱,动画的瞬间不得不来回传递上下两个 Activity 各种控件的 Bitmap;
  • Android 9 之前 Activity 每次启动新的 Activity,都需要上个页面执行完 onSaveInstance,这一步影响了页面打开的速度;
  1. Activity 依赖 Manifest 给 Android 动态化增加了难度,需要对系统的 Instrumentation ActivityThread 进行各种 Hack ;
  2. 依赖注入很难,因为创建 Activity 对象的流程在 Android 8 之前是没有 API 暴露给外部处理的;
  3. 因为 Window 的机制导致做悬浮窗播放也是问题,导致实现窗口播放必须依赖了一个危险的悬浮窗权限;
  4. 共享元素动画在某些版本的 Framework 层有 NPE,无法解决。

java.lang.NullPointerException(android.app.EnterTransitionCoordinator);

页面组合对比 Fragment

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

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState

对于这种情况,西瓜直接在自己的 Activity 基类对 super.onBackPressed() 进行了try catch。

  1. add/remove/hide/show 操作不是立刻执行,就算 commitNow 执行了 Fragment 的状态,也不能保证他的 Child Fragment 状态刷新到最新。在执行了 getChildFragmentManager().executePendingTransactions() 后,开发者会误以为 Child Fragment 都已经切到最新的 Parent Fragment 状态,其实并没有;
  2. Fragment 有两套 Lifecycle,View Lifecycle 和 Fragment 实例 Lifecycle;
  3. Fragment show/hide 方法不会触发生命周期回调,调用了 hide 不会触发 onPause/onStop,只是修改了 View 的可见性;
  4. Fragment 动画能力有限,只能使用资源文件,而且页面导航无法保证 Z 轴正确;
  5. 就算 Fragment 已经被销毁,但是 View.OnClickListener onClick 回调依然继续触发,导致回调内部不得不补大量的判空逻辑;

if (getActivity() == null) {
return;
}

  1. 导航功能非常弱,除了打开和关闭,没有更加高级的栈管理,导航的回调连顺序都保证不了,有可能一次导航触发多次回调;
  2. 原生 Fragment 和 Support Fragment 的生命周期并不完全相同;
  3. 同时支持 add/remove/hide/show+addToBackStack 使得 Fragment 的代码极度混乱。

Scene 框架

功能特点

Scene 提供页面导航页面组合两大功能,特点如下:

  1. 基于 View 实现,非常轻量;
  2. 只有一个 Lifecycle,View 销毁,那么 Scene 也会销毁,不会出现 Fragment 有两套 Lifecycle 的问题;
  3. 导航栈管理非常灵活,不会出现页面切换黑屏问题;
  4. 无论是导航操作还是组合操作,通常都是直接执行,不需要区分 commit 和 commitNow;
  5. 不强制要求状态保存,甚至可以把状态保存控制在页面级别,增强组件通讯的能力;
  6. 有完整的共享元素动画支持;
  7. 页面导航和页面组合功能可以独立使用。

基本概念

Scene 框架有3种基本组件:Scene、NavigationScene、GroupScene。

用处
Scene所有 Scene 的基类,带生命周期和 View 支持的组件
NavigationScene支持页面导航
GroupScene支持将任何 Scene 组合

Scene

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

NavigationScene

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

GroupScene

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Scene 使用

简单使用

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

接入

添加依赖:

dependencies {
implementation ‘com.bytedance.scene:scene: l a t e s t v e r s i o n ′ i m p l e m e n t a t i o n ′ c o m . b y t e d a n c e . s c e n e : s c e n e − u i : latest_version' implementation 'com.bytedance.scene:scene-ui: latestversionimplementationcom.bytedance.scene:sceneui:latest_version’
implementation ‘com.bytedance.scene:scene-shared-element-animation:$latest_version’

// Kotlin
implementation ‘com.bytedance.scene:scene-ktx:$latest_version’
}

创建首页:

class MainScene : AppCompatScene() {
override fun onCreateContentView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle?): View? {
return View(requireSceneContext())
}

override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setTitle(“Main”)
toolbar?.navigationIcon = null
}
}

创建 Activity:

class MainActivity : SceneActivity() {
override fun getHomeSceneClass(): Class {
return MainScene::class.java
}

override fun supportRestore(): Boolean {
return false
}
}

添加到 Manifest.xml,注意把输入法模式也改了:






运行就可以了。

这是新应用想全部使用 Scene 写的方式。如果是老应用重构迁移,或者只想用页面组合替代 Fragment,导航依旧用 Activity 的做法,可以见 Github 的 Demo。

导航

打开新页面:

requireNavigationScene().push(TargetScene::class.java)

返回:

requireNavigationScene().pop()

打开页面拿结果:

requireNavigationScene().push(TargetScene::class.java, null,
PushOptions.Builder().setPushResultCallback { result ->
}
}.build())

设置结果:

requireNavigationScene().setResult(this@TargetScene, YOUR_RESULT)

组合

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

void add(@IdRes int viewId, @NonNull Scene childScene, @NonNull String tag);
void remove(@NonNull Scene childScene);
void show(@NonNull Scene childScene);
void hide(@NonNull Scene childScene);
@Nullable
T findSceneByTag(@NonNull String tag);

示例:

class SecondScene : AppCompatScene() {
private val mId: Int by lazy { View.generateViewId() }

override fun onCreateContentView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle?): View? {
val frameLayout = FrameLayout(requireSceneContext())
frameLayout.id = mId
return frameLayout
}

override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setTitle(“Second”)
add(mId, ChildScene(), “TAG”)
}
}
class ChildScene : Scene() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle?): View {
val view = View(requireSceneContext())
view.setBackgroundColor(Color.GREEN)
return view
}
}

通讯

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

class ViewModelSceneSamples : GroupScene() {
private val viewModel: SampleViewModel by activityViewModels()

示例:

class ViewModelSceneSamples : GroupScene() {
private val viewModel: SampleViewModel by activityViewModels()
private lateinit var textView: TextView

override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel.counter.observe(this, Observer { t -> textView.text = “” + t })

add(R.id.child, ViewModelSceneSamplesChild(), “Child”)
}
}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

更多Android高级工程师进阶学习资料

进阶学习视频

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

ndroid基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

[外链图片转存中…(img-QlHSJlCF-1713604980820)]

里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值