我一直在努力思考将 Android Services 放置在新的Android 推荐的 Architecture中的哪个位置。我想出了许多可能的解决方案,但我无法决定哪一个是最好的方法。
我做了很多研究,但找不到任何有用的指南或教程。我发现的关于在我的应用程序架构中放置服务的唯一提示是这个,来自@JoseAlcerreca Medium 帖子
理想情况下,ViewModel 不应该对 Android 有任何了解。这提高了可测试性、泄漏安全性和模块化。一般的经验法则是确保您的 ViewModel 中没有 android.* 导入(android.arch.* 等例外情况除外)。这同样适用于演讲者。
据此,我应该将我的 Android 服务放在架构组件层次结构的顶部,与我的活动和片段处于同一级别。那是因为 Android 服务是 Android 框架的一部分,所以 ViewModel 不应该知道它们。
现在,我将简要解释一下我的场景,但只是为了让全景更清晰,而不是因为我想要这个特定场景的答案。
- 我有一个 Android 应用程序,它有一个 MainActivity,里面有很多片段,所有这些片段都捆绑在一个 BottomNavBar 中。
- 我有一个绑定到 myActivity 及其片段之一的 BluetoothService(因为我希望服务具有与 Activty 相同的生命周期,但我也想直接从我的片段与其交互)。
- 该片段与 BluetoothService 交互以获取两种类型的信息:
- 有关蓝牙连接状态的信息。不需要坚持。
- 来自蓝牙设备的数据(它是一个秤,在这种情况下是体重和身体成分)。需要坚持。
以下是我能想到的 3 种不同的架构:
AndroidService 中的 LiveData
更新:这是我个人当时采用的方法,因为它运作良好,让我能够相对快速地完成它。但是,我建议遵循 Jeel Vankhede 的更新答案,以获得似乎更“惯用”的实现。
- 带有连接状态和来自蓝牙设备的重量测量值的 LiveData 在 BluetoothService 中。
- Fragment 可以触发 BluetoothService 中的操作(例如 scanDevices)
- Fragment 观察有关连接状态的 LiveData 并相应地调整 UI(例如,如果状态为连接,则启用按钮)。
- Fragment 观察新体重测量的 LiveData。如果来自 BluetoothDevice 的新重量测量值,则 Fragment 会告诉它自己的 ViewModel 保存新数据。它是通过 Repository 类完成的。
在 Fragment 和 AndroidService 之间共享 ViewModel
- Fragment 可以触发 BluetoothService 中的操作(例如 scanDevices)
- BluetoothService 更新共享 ViewModel 中的蓝牙相关 LiveData。
- Fragment 在自己的 ViewModel 中观察 LiveData。
- Fragment 可以触发 BluetoothService 中的操作(例如 scanDevices)
- BluetoothService 在自己的 ViewModel 中更新与蓝牙相关的 LiveData。
- Fragment 在自己的 ViewModel 和 BluetoothService ViewModel 中观察 LiveData。
我很确定我应该将它们放在架构之上,并将它们视为 Activity/Fragment,因为 BoundServices 是 Android 框架的一部分,它们由 Android 操作系统管理,并且绑定到其他 Activity 和 Fragment。在这种情况下,我不知道与 LiveData、ViewModel 和活动/片段交互的最佳方式是什么。
有些人可能认为它们应该被视为数据源(因为在我的例子中,它是使用蓝牙从秤中获取数据),但我认为这不是一个好主意,因为我在上一段中说过特别是因为它在这里说的:
避免将应用程序的入口点(例如活动、 服务和广播接收器)指定为数据源。相反,它们应该只与其他组件协调以检索与该入口点相关的数据子集。每个应用程序组件的寿命都很短,具体取决于用户与其设备的交互以及系统当前的整体健康状况。
所以,最后,我的问题是:
我们应该将我们的 Android(绑定)服务放在哪里,它们与其他架构组件的关系是什么?这些替代方案中的任何一个都是好方法吗?