跟着 UI
架构的变迁和技术的迭代,界面间数据传递的方法也变得多种多样了。没有最好的方法,只要当时合适事务的方法。今天咱们就来看看有哪些数据传递的方法,咱们又该怎样选择?
在最开端的时分,界面仅仅运用 startActivityForResult
来进行页面间的数据传递,后边 Fragment
诞生,官方也供给了 FragmentManager.setFragmentResultListener
之类的方法,但 Jetpack Compose
之后,官方就完全弱化了这方面的才能。
在探索详细的技术细节前,咱们要先看看咱们数据需求传输的场景有哪些:
- 启动新界面是为了获取某些数据,然后回来给当时界面用,例如相片选择器。
- 几个界面是为了合作完结一件工作,每个界面担任一部分流程,例如注册流程。
- 界面的某些改动,需求告诉到其它界面,例如用户关注的改变,一旦改变,则希望其它界面也可以同步更新。
大多数状况下,咱们所说的数据传输都是针对第一种状况而言。最基础的便是 startActivityForResult
。当然,现在应该没人直接用这个了,都是用官方封装的 LauncherForActivityResult
了:
val launcher = rememberLauncherForActivityResult(contract = ActivityResultContracts.GetContent(), onResult = {uri ->
// ...
})
如果运用的是 Fragment
, 曾经可以运用十分不好用的 setTargetFragment
, 现在则可以运用 FragmentManager.setFragmentResultListener
,与 Activity
的运用是迥然不同。
而如果是运用 Jetpack Compose Navigation
, 那不好意思,现在还十分不成熟,一个可用的方法是运用 previousBackStackEntry
:
// 新界面运用 previousBackStackEntry 获取到前一个界面的数据存储,然后往里面设置数据
navController.previousBackStackEntry
?.savedStateHandle
?.set("your_key", "your_value")
navController.popBackStack()
// 回来到原本的界面后,经过 currentBackStackEntry 去读取数据存储。
val savedStateHandle = navController.currentBackStackEntry?.savedStateHandle
虽然咱们也可以参照 Fragment
的完结用 ActivityViewModel
构建一套 ComposeResultListener
之类的完结。但估计跟着版别的迭代和大众的呼声,官方也会出品接口更友爱的方法。而如果咱们自己完结的话,就可以在官方出品后对比下,看看差距,才知道怎样写出更好的代码。
但需求记住的是,这二者都是不能跨越 Activity
而通信的。如果是多 Activity
多 Page
架构,则需求注意这种状况。我觉得,这种界面一般是通用型的组件界面,所以一般运用 Activity
作为载体就好。
如果是几个界面合作完结某件工作,需求相互共享一些数据,那就可以把这几个界面包裹在同一个 Activity
里,运用 ActivityViewModel
作为数据的载体,每个界面监听 ActivityViewModel
的数据,那么便是完美的数据驱动 UI
了。
在 emo
的 photo
库中,相片选择器有 grid
界面、preview
界面、edit
界面,其三者都收归在 PhotoPickerActivity
, 共享 PhotoPickerViewModel
来进行数据管理, 最后再经过 ActivityResult
交给外部调用者,这也是第一种方法与第二种方法的结合。
而事务上运用最常见的方法应该是第三种了,便是我增修改查了些数据,希望其它界面也可以立刻同步到,不要呈现各个界面不对齐的状况。Channel
、StateFlow
、SharedFlow
等数据流东西都可以助力咱们数据驱动 UI
,当然,最便利的形式便是运用 emo
封装的 EmoBus
。
// 界说数据改变事情
data class AddCommentSuccessEvent(val thinkId: Long, val id: Long, val draftId: Long)
// A 界面发送事情
EmoBus.default.emit(AddCommentSuccessEvent(content.itemId, id, draft.id))
// B 界面监听事情
EmoBus.default.flowOf<AddCommentSuccessEvent>().collect {
// ...
}
基本上咱们可以用于页面间数据传递与运用的就这些形式了,咱们只需求在需求的场景选用恰当的方法就可以了。
我是古哥E下,前微信读书客户端程序猿 / 自学 5 年中医,保护过上万 Star 开源项目 QMUI Android
,现独立保护好用简练的 Android
组件库 emo
。
关注我可得:ChatGPT
开发玩法 | 程序员学习经验 | 组件库新变动 | 中医健康调度 。
emo官网:emo.qhplus.cn