如何在Fragment之间共享数据?
在日常的需求迭代中,我们经常会遇到 Fragment 之间共享数据的需求,比如 Fragment A 的数据需要给 Fragment B ,有什么样的方案可以实现呢?
普通的解决方案
对于这个问题,一般很容易想到在 Activity 中加一个字段来解决,比如:
MainActivity.kt
1 | class MainActivity : FragmentActivity() { |
这样就可以在 Fragment 中通过 MainActivity 来拿到共享的数据了,例如:
Fragment1.kt
在 Fragment1 中,从 API 获取数据,然后,更新到 MainActivity 中:
1 | class Fragment1 : Fragment() { |
Fragment2.kt
在创建 Fragment2 时,从 MainActivity 中获取由 Fragment1 共享的数据,然后更新 UI ,例如:
1 | class Fragment2 : Fragment() { |
这样确实能解决数据共享问题,但是,大家有没有发现这个方案的弊端?
SharedData其实是由Fragment1来维护的,如果把SharedData放到MainActivity里,就会导致维护SharedData的职责不清晰;如果还有别的数据需要在其它的
Fragment之间共享,都往MainActivity里加的话,无疑给MainActivity带来了过多的不必要的负担,而且,这也不是MainActiivty的职责所在;如果
Fragment1不仅在MainActivity里用到,而且还在其它的Activity用到,那如何保证Fragment1在不同的Activity复用而不会带来额外的维护成本?
优雅的解决方案
对于前面的方案的弊端,主要在于两个方面:
- 职责范围 - Responsibility
- 可扩展性 - Scalability
对于上面的需求,理想的方案应该是:
SharedData只应由Fragment1维护- 不需要修改
MainActivity
如果要满足上面的条件的话,Fragment1 大概是长这样:
1 | class Fragment1 : Fragment() { |
但如果是这样的话,会有几个问题:
Fragment2如何方便的从Fragment1拿到SharedData的引用呢?- 如果
Fragment1被销毁了,那SharedData也就拿不到了,如何让SharedData跟MainActivity的生命周期绑定呢?
针对上面的问题,我们可以采用下面的方案:
LifecycleScope.kt
1 | object LifecycleScope : LifecycleObserver { |
Fragment1.kt
1 | class Fragment1 : Fragment() { |
Fragment2.kt
1 | class Fragment2 : Fragment() { |
这样,既不用修改 MainActivity,Activity 也完全不关心 Fragment 之间的共享行为,这样 Fragment 变得更内聚,而且在其它 Activity 中无成本复用 Fragment。
完美的解决方案
上面的方案虽然优雅,但需要额外的增加 LifecycleScope 这个类,而且,LifecycleScope 是一个单例,虽然性能上不会有太大问题,但总是感觉不够完美,那有没有更完美的解决方案呢?
其实 Android 官方已经提供了现成的方案 —— ViewModel,如果采用 ViewModel 来实现上面的需求,应该长啥样呢?
SharedViewModel.kt
1 | class SharedViewModel : ViewModel() { |
Fragment1.kt
1 | class Fragment1 : Fragment() { |
Fragment2.kt
1 | class Fragment2 : Fragment() { |
一般情况下,在 Fragment 中使用 ViewModel 都是调用 viewModels() 这个扩展方法,并通过 by 来创建一个 ViewModel 的 Delegate ,然后这个 ViewModel 的 Delegate 是跟 Fragment 的生命周期绑定的,如果要在 Fragment 销毁后依赖能共享给其它的 Fragment 就需要调用 activityViewModels() 来将 ViewModel 的 Delegate 跟 Activity 的生命周期绑定。
- 本文链接:https://johnsonlee.io/2020/12/05/sharing-data-between-fragments/
- 版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。