我一直在努力思考在新的 Android recommended Architecture 中放置 Android 服务的位置。我想出了许多可能的解决方案,但我无法决定哪一个是最好的方法。
我做了很多研究,但找不到任何有用的指南或教程。我发现的关于在我的应用程序架构中放置服务的唯一提示是这个,来自@JoseAlcerreca Medium post
理想情况下,ViewModel 不应该对 Android 有任何了解。这提高了可测试性、泄漏安全性和模块化。一般的经验法则是确保您的 ViewModel 中没有 android. 导入(android.arch. 等例外情况除外)。这同样适用于演讲者。
据此,我应该将我的 Android 服务放在架构组件层次结构的顶部,与我的活动和片段处于同一级别。那是因为 Android 服务是 Android 框架的一部分,所以 ViewModel 不应该知道它们。
现在,我将简要解释一下我的场景,但只是为了让全景更清晰,而不是因为我想要这个特定场景的答案。
- 我有一个 Android 应用程序,它有一个 MainActivity,里面有很多片段,所有这些片段都捆绑在一个 BottomNavBar 中。
- 我有一个绑定到 myActivity 及其片段之一的 BluetoothService(因为我希望服务具有与 Activty 相同的生命周期,但我也想直接从我的片段与其交互)。
- Fragment与BluetoothService交互,获取两种信息:
*有关蓝牙连接状态的信息。不需要坚持。- 来自蓝牙设备的数据(它是一个秤,在这种情况下是体重和身体成分)。需要坚持。
以下是我能想到的 3 种不同的架构:
AndroidService 中的 LiveData
**UPDATE: This is the approach I personally went with at the time because it worked well and allowed me to get it done relatively fast. However, I suggest following the updated answer by Jeel Vankhede for what seems to be a more "idiomatic" implementation.**
- 带有连接状态和来自蓝牙设备的重量测量值的 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 和活动/片段交互的最佳方式是什么。
有些人可能认为它们应该被视为数据源(因为在我的例子中,它是使用蓝牙从秤中获取数据),但我认为这不是一个好主意,因为我在上一段中说过特别是 because of what it says here :
避免将应用程序的入口点(例如活动、服务和广播接收器)指定为数据源。相反,它们应该只与其他组件协调以检索与该入口点相关的数据子集。每个应用程序组件的寿命都很短,具体取决于用户与其设备的交互以及系统当前的整体健康状况。
所以,最后,我的问题是:
我们应该在哪里放置我们的 Android(绑定)服务以及它们与其他架构组件的关系是什么?这些替代方案中的任何一个都是好方法吗?
在仍然能够使用它的同时避免直接接触 Android 服务的一种方法是通过接口对象。这是首字母缩略词
SOLID
中接口隔离**“I”的一部分。这是一个小例子:鉴于上述范例,您可以自由地将服务放在包含 POJO 代码的包之外的包中。没有“正确”的位置来放置您的服务——但肯定有放置它们的错误位置(例如,您的 POJO 代码所在的位置)。