简体   繁体   English

Android Ble客户端应用架构

[英]Android Ble client app architecture

it's more a general question rather than a specific one. 这更是一个普遍的问题,而不是一个具体的问题。

Basically I'm developing an Android app which communicates with Ble Peripheral Device. 基本上,我正在开发一个与Ble Peripheral Device通信的Android应用程序。 I handle Ble communication using RxAndroidBle library. 我使用RxAndroidBle库处理Ble通信。 As for the general pattern, I decided to try Mosby MVI, however that's not that important. 至于一般模式,我决定尝试使用Mosby MVI,但这并不那么重要。

What I did so far is I created BluetoothManager class which is responsible for performing all the operations on the Ble Device. 到目前为止,我创建了BluetoothManager类,该类负责在Ble设备上执行所有操作。 This class is a Singleton (I know it's not recommended on Android) and I scoped it using Dagger, that this is injected only to those interactors that should perform some Ble communication. 此类是Singleton(我知道在Android上不建议使用),并且我使用Dagger对其进行了范围划分,这仅注入那些应该执行某些Ble通信的交互器。 This class returns Observables with some POJOs, which are transformed to ViewStates in interactor and than moved higher to the UI. 此类返回带有一些POJO的Observable,这些POJO在交互器中转换为ViewStates,然后移至UI更高的位置。 Subscriptions are in the presenters following Mosby MVI pattern. 订阅者遵循Mosby MVI模式在演示者中订阅。

Basically thanks to that I treat this Ble Device as a regular data source, same as some retrofit service or any db. 基本上,由于这个原因,我将此Ble设备视为常规数据源,与某些翻新服务或任何数据库一样。 And that was totally fine as long as I was performing atomic operations like writing and reading some single characteristics. 只要我执行原子性操作(如编写和读取某些单个特征),那完全没问题。

The problem is when I need to fire up some kind of a synchronization that may take quite a lot of time, should be done on background, should NOT be bound to UI, however on some screens user should be able to see the progress. 问题是当我需要启动某种类型的同步时(可能需要花费很多时间),应该在后台执行,不应该绑定到UI,但是在某些屏幕上,用户应该可以看到进度。 Here I started to think about using Android Service and putting all the Ble Communication logic there, however in my opinion using Android service breaks any attempts of logic separation and I couldn't find a good way to fit it there. 在这里,我开始考虑使用Android Service并将所有的Ble Communication逻辑放在这里,但是我认为使用Android Service破坏了逻辑分离的任何尝试,并且我找不到在其中安装它的好方法。

Third option was having a service for synchronization and preserving BluetoothManager for atomic operations bounded to UI, however I think it's messy and I would be nice to have all the Ble stuff in one place. 第三种选择是提供一个同步服务,并为绑定到UI的原子操作保留BluetoothManager,但是我认为这很麻烦,将所有Ble东西放在一个地方也很好。

I know it's long but it all goes to one question -> what would be the best pattern to follow when communicating with Ble device on Android to preserve layers separation and keeping it as independent as possible. 我知道这很长,但是全部都涉及一个问题->与Android上的Ble设备进行通信以保持层分离并使其尽可能独立时,遵循的最佳模式是什么? I could not find any good articles about handling that, if there are any they are quite out dated, not using Rx approach. 我找不到任何有关处理该问题的好文章,如果有的话它们已经过时了,请不要使用Rx方法。 If it's too generic, I can specify some more details, but I'm looking more for an architectural advice rather than code snippets. 如果过于笼统,我可以指定更多细节,但我更多的是寻求体系结构建议,而不是代码段。

What about something like this: instead of subscribing in presenter to bluetooth directly, introduce a class BleRepository 像这样的事情呢:引入一个BleRepository类,而不是直接在主持人中订阅蓝牙。

Then BleRepository provides a metod Observable<Foo> (Foo is whatever data your Presenter / UI should see) and operations to execute stuff like doA() . 然后BleRepository提供了一个方法Observable<Foo> (Foo是Presenter / UI应该看到的任何数据)和执行诸如doA()类的操作的操作。 Something like this: 像这样:

interface BleRepository {


   // Read Data
   Observable<Foo> getDataObservable();

   // Write Data operations
   Completable doA();
   Completable doB(); 

}

So the Presenter subscribes to BleRepository instead to bluetooth connection directly. 因此,演示者直接订阅BleRepository而不是蓝牙连接。

So now whenever you do a "write operation" you just execute it but you always read new data from getDataObservable() even if the write operation itself returns new data, reading data always goes through getDataObservable() . 所以,现在当你做一个“写操作”你只是执行它,但你总是读取新的数据getDataObservable()即使写入操作本身返回的新数据,读取数据总是通过云getDataObservable()

So BleRepository is basically just a public API your presenter uses. 因此, BleRepository基本上只是演示者使用的公共API。 The Presenter doesn't know about the actual Bluetooth connection. 演示者不知道实际的蓝牙连接。 So what you can do next is moving the actual bluetooth connection into an android service, lets call it BluetoothService . 因此,接下来您可以将实际的蓝牙连接移动到android服务中,将其称为BluetoothService Then BluetoothService get's connected and whenever the sync runs or whatever else your connection receives / sends, it emits that data back to BleRepository.getDataObservable() which is subscribed by the service. 然后建立BluetoothService的连接,并且每当同步运行或您的连接接收/发送的任何其他内容时,它将BleRepository.getDataObservable()数据发送回该服务订阅的BleRepository.getDataObservable() You just have to ensure that both Service and Presenter "share" the same BleRepository instance. 您只需要确保Service和Presenter都“共享”相同的BleRepository实例。 ie use dagger to inject the same instance or make it a singleton ... whatever works best for you. 即使用匕首注入相同的实例或使其成为一个单例……最适合您的方法。

Depending on your usecase you can also make the BluetoothService subscription aware like start the android service in RxJavas onSubscribe and stop the service in on unsubscribe / onTerminal. 根据您的用例,您还可以使BluetoothService订阅知道,例如在RxJavas onSubscribe中启动android服务,并在unsubscribe / onTerminal中停止该服务。 But it sounds like your usecase is slightly different so that Bluetooth is still connected even if Presenter / view has been destoryed, right? 但这听起来好像您的用例略有不同,所以即使Presenter /视图已被破坏,蓝牙仍可以连接,对吗? Whatever, the idea is use Service (Services if it makes sense for your proble) but they all somehow push the data into BleRepository that then delivers the data to the Presenter. 无论如何,其主意是使用服务(如果对您的问题有意义,则使用服务),但是它们都以某种方式将数据推送到BleRepository中,然后将数据传递到Presenter。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM