新的Android推荐架构中的BoundService + LiveData + ViewModel最佳实践 [英] BoundService + LiveData + ViewModel best practice in new Android recommended architecture

本文介绍了新的Android推荐架构中的BoundService + LiveData + ViewModel最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在苦苦思索在新的 Android推荐的体系结构中将Android服务放置在何处.我想出了许多可能的解决方案,但是我无法决定哪种方法是最好的方法.

I been struggling a lot thinking about where to place Android Services in the new Android recommended Architecture. I came up with many possible solutions, but I cannot make up my mind about which one is the best approach.

我做了很多研究,但是找不到任何有用的指南或教程.我发现有关将服务放置在我的应用程序体系结构中的唯一提示就是来自@JoseAlcerreca 中级帖子

I did a lot of research, and I couldn't find any useful guideline nor tutorial. The only hint I found about where to place the Service in my app architecture is this one, from @JoseAlcerreca Medium post

理想情况下,ViewModels应该对Android一无所知.这提高了可测试性,泄漏安全性和模块化性.一般的经验法则是确保ViewModels中没有android.*导入(像android.arch.*这样的例外).演示者也是如此.

Ideally, ViewModels shouldn’t know anything about Android. This improves testability, leak safety and modularity. A general rule of thumb is to make sure there are no android.* imports in your ViewModels (with exceptions like android.arch.*). The same applies to presenters.

因此,我应该将Android服务放置在架构组件"层次结构的顶部,并与活动和片段"处于同一级别.那是因为Android服务是Android框架的一部分,所以ViewModels不应了解它们.

According to that, I should place my Android Services on the top of my Architecture Components hierarchy, at the same level as my Activities and Fragments. That's because Android Services are part of the Android framework, so ViewModels shouldn't know about them.

现在,我将简要说明我的情况,但这只是为了使全景图更清晰,而不是因为我想要针对此特定情况的答案.

Now, I will explain briefly my scenario, but only to make the panorama clearer, not because I want an answer for this specific scenario.

  • 我有一个Android应用程序,其中包含MainActivity,其中包含许多片段,所有片段都在BottomNavBar中绑在一起.
  • 我有一个绑定到myActivity及其片段之一的BluetoothService(因为我希望该服务具有与Activty相同的生命周期,但我也想直接从我的片段与其进行交互).
  • 该片段与BluetoothService交互以获取两种类型的信息:
    • 有关蓝牙连接状态的信息.不需要坚持.
    • 来自蓝牙设备的数据(它是一个秤,因此在这种情况下为体重和身体成分).需要坚持下去.
    • I have an Android Application that has a MainActivity with many fragments in it, all of them tied together in a BottomNavBar.
    • I have a BluetoothService bound to myActivity and one of its fragments (because I want the Service to have the same lifecycle as the Activty but I also want to interact with it directly from my fragment).
    • The fragment interacts with the BluetoothService to get two types of information:
      • Information about the state of the Bluetooth connection. Doesn't need to be persisted.
      • Data that comes from the Bluetooth Device (it is a Scale, so weight and body composition in this case). Needs to be persisted.

      以下是我可以想到的3种不同的架构:

      Here are the 3 different architectures I can think of:

      AndroidService中的LiveData

      • 具有连接状态和权重的LiveData 来自Bluetooth设备的测量值位于BluetoothService内部.
      • 该片段可以触发BluetoothService中的操作(例如scanDevices)
      • 该片段观察有关连接状态的LiveData 并相应地调整用户界面(例如,如果 状态已连接).
      • 该片段会观察新的重量测量结果的LiveData.如果新的重量测量值来自BluetoothDevice,则Fragment然后告诉其自己的ViewModel保存新数据.这是通过Repository类完成的.
      • The LiveData with the state of the connection and with the weight measurements coming from the Bluetooth Device are inside the BluetoothService.
      • The Fragment can trigger operations in the BluetoothService (scanDevices for example)
      • The Fragment observes the LiveData about the state of the connection and adapts the UI accordingly (for example, enable a button if the state is connected).
      • The Fragment observes the LiveData of the new weight measurements. If a new weight measurement comes from the BluetoothDevice, the Fragment then tells its own ViewModel to save the new data. It is done via a Repository class.

      片段和AndroidService之间共享的ViewModel

      • 该片段可以触发BluetoothService中的操作(例如scanDevices)
      • BluetoothService在共享的ViewModel中更新与Bluetooth相关的LiveData.
      • 该片段在其自己的ViewModel中观察LiveData.

      服务ViewModel

      • 该片段可以触发BluetoothService中的操作(例如scanDevices)
      • BluetoothService在其自己的ViewModel中更新与蓝牙相关的LiveData.
      • 该片段在其自己的ViewModel和BluetoothService ViewModel中观察LiveData.

      我很确定我应该将它们放在架构之上,并像对待活动/片段一样对待它们,因为BoundServices是Android Framework的一部分,它们由Android OS管理,并且与其他Activity和碎片.在那种情况下,我不知道与LiveData,ViewModels和Activity/Fragments进行交互的最佳方式是什么.

      I am pretty sure I should place them on top of the architecture and treat them just like an Activity/Fragment, because BoundServices are part of the Android Framework, they are managed by the Android OS and they are bound to other Activities and Fragments. In that case, I don't know what's the best way to interact with LiveData, ViewModels and Activities/Fragments.

      有些人可能认为应该将它们视为数据源(因为在我的情况下是使用蓝牙从秤中获取数据),但是我认为这不是一个好主意,因为我在上面已经说了很多.上一段,特别是由于此处所说的内容:

      Some might think that they should be considered as a DataSource (since in my case it's getting data from a scale using Bluetooth), but I don't think this is a good idea, because of all what I've said in the previous paragraph and specially because of what it says here:

      避免指定应用的入口点,例如活动, 服务和广播接收器-作为数据源.相反,他们应仅与其他组件协调以检索 与该入口点相关的数据子集.每个应用 组件的寿命很短,具体取决于用户的交互 以及他们的设备和系统的整体当前运行状况.

      Avoid designating your app's entry points—such as activities, services, and broadcast receivers—as sources of data. Instead, they should only coordinate with other components to retrieve the subset of data that is relevant to that entry point. Each app component is rather short-lived, depending on the user's interaction with their device and the overall current health of the system.

      所以,最后,我的问题是:

      So, finally, my question is:

      我们应该在哪里放置我们的Android(绑定)服务,它们与其他架构组件之间的关系是什么?这些替代方法中的任何一种都是好的方法吗?

      推荐答案

      我认为 服务 应该与 活动/片段 ,因为它是框架组件&不是 MVVM .但由于该服务未实现 LifecycleOwner ,它是Android Framework组件,因此不应将其视为数据源,因为它可以成为应用程序的入口点.

      In my opinion, Service should be on same level as Activity/Fragment, because it's Framework component & not MVVM. but because of that Service doesn't implements LifecycleOwner and it's Android Framework Component, it shouldn't be treated as data source because it can be entry point to application.

      因此,这里的难题是有时(在您的情况下),Service充当数据源,该数据源从长时间运行的任务向UI提供数据.

      So, dilemma here is that sometimes (In your case), Service acts as data source which provides data from some long running task to UI.

      那么 Android体系结构组件中应该有什么?我认为您可以将其视为 LifecycleObserver .因为,无论您在后台做什么,都需要考虑 LifecycleOwner 的生命周期.

      So what it should be in Android Architecture Component? I think you can treat it as LifecycleObserver. because, no matter what you do in background, you'll need to consider about lifecycle of the LifecycleOwner.

      为什么?因为我们通常会将其绑定到 LifecycleOwner (活动/片段)&在UI上执行长时间运行的任务.因此,可以将其视为 LifecycleObserver .通过这种方式,我们将服务作为"生命周期感知组件" !

      Why? because, we usually do bind it to LifecycleOwner (Activity/Fragments) & to do long running tasks off the UI. So, it can be treated like LifecycleObserver. In such a way we made our Service as "Lifecycle aware component" !

      如何实现它?

      1. 获取您的服务类并为其实现 LifecycleObserver 接口.

      在将服务绑定到Activity/Fragment时,在服务类的服务连接期间,通过调用方法getLifecycle().addObserver(service class obj)

      When you bind your service to Activity/Fragment, during your service connection of your service class, add your service to your activity as LifecycleObserver by calling method getLifecycle().addObserver(service class obj)

      现在,在服务类中获取一个接口,以提供从服务到UI的回调,并且每次数据更改时,请检查服务是否至少在生命周期事件中发生

      Now, Take an interface in service class to provide callback from service to your UI and every time your data changes, check that if your service has at least on Lifecycle event create or resume to provide callback with.

      这样,我们将不需要LiveData从服务更新到更新,甚至不需要ViewModel (为什么我们需要它来进行服务?我们不需要配置更改就可以在服务中生存下来) VM的主要任务是在生命周期之间包含数据)..

      In such a way, we won't require LiveData to update to from service and even no ViewModel (Why do we need it for service? We don't need configuration changes to survive on service lifecycle. And main task to VM is that to consist data between lifecycles).

      在收到@Ibrahim Disouki的建议后(谢谢您),我深入研究并发现了一些有趣的东西!这是背景.

      After getting suggestion from @Ibrahim Disouki (Thank you for that) I dig deeper and found out something interesting! Here's background.

      TL; DR :

      如果您到目前为止已做到这一点,则意味着您没有通读以上解决方案&我很高兴您没有,因为在阅读以下内容后,这毫无意义.因此,请忘记上述方法(很抱歉,最近)

      If you've made it so far which means you didn't read through above solution & I'm glad you didn't, because that doesn't make any sense after reading following. So, forget about above approach (Sorry about that lately)

      回到重点:

      O.P.寻找解决方案" Android框架的服务组件在考虑Android体系结构组件的情况下".因此,这是现成的(SDK)解决方案.

      O.P. seeks for solution "Where Service component of Android Framework stands considering Android Architecture Components". So, here's out the box(SDK) solution.

      它与Activity/Fragment处于同一级别.如何?如果您不是在扩展Service类,则开始扩展 LifecycleService .原因很简单,以前我们不得不依靠Activity/Fragment生命周期来接收更新/对Service进行一些上下文操作.但是现在情况并非如此.

      It stands at the same level as Activity/Fragment. How? If you're extending Service class though rather than that, start extending LifecycleService. Reason behind that is simple that previously we had to rely on Activity/Fragment lifecycle in order to receive updates/do some contextual operations on Service. But now it's not the case.

      LifecycleService现在拥有自己的名为ServiceLifecycleDispatcher的生命周期注册表/维护程序,它负责服务的生命周期,这也使其成为LifecycleOwner.

      LifecycleService now has it's own lifecycle registry/maintainer called ServiceLifecycleDispatcher which takes care of lifecycle of service which also makes it LifecycleOwner.

      这使我们处于从现在开始的条件下,您可以让ViewModelLifecycleService为其自身进行操作&如果您遵循正确的应用程序体系结构,并且拥有存储库模式,那么您将只有一个真相!

      It leaves us in condition that from now on, You can have a ViewModel to LifecycleService doing operations for itself & if you're following proper app architecture and having repository pattern leaves you to single source of truth!

      在OP LifecycleService的上下文中,现在可以保持执行与存储库层相关的业务逻辑的ViewModel的能力,稍后在另一个生命周期感知的组件(如Activity/Fragment)也可以使用/重用相同的ViewModel来具有他们的具体操作.

      In context of O.P. LifecycleService now can have ability to maintain it's ViewModel to do business logic related to repository layer, and later on another lifecycle aware component like, Activity/Fragment can also consume/reuse same ViewModel to have their specific operations to it.

      请注意,这样做会导致您拥有两个不同的LifecycleOwner s (活动和生命周期服务) ,这意味着您无法在LifecycleService和& amp; amp;之间共享视图模型;其他生命周期感知组件.如果您不喜欢这种方法,那么可以使用旧的回调方法,当数据准备好提供服务时,可以将回调从服务回调回Activity/Fragment.

      Please note that by doing so, you're in state of having two different LifecycleOwners (Activity & LifecycleServie) which means you can't share view models between LifecycleService & other lifecycle aware components. If you don't like approach then be good with old callback kind of approach having callbacks back to Activity/Fragment from service when data is ready to serve etc.

      侧面注意:如果您认为自己正在长时间运行后台操作,请考虑使用WorkManager.使用该库后,您会觉得现在应该将Services标记为已弃用. ! (只是一个随机的想法)

      这篇关于新的Android推荐架构中的BoundService + LiveData + ViewModel最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆