Android Service在MVP模式中应该扮演什么角色?

10

我正在开发一款安卓应用,它可以进行人类活动识别。

基本上是这样工作的 - 服务不断读取加速器数据并将识别出的活动(例如步行、奔跑)存储在数据库中。用户可以在一个 ListView 中查看所有识别出的活动(访问数据库)。数据库中的每个用户表都有一个pa_goal(身体活动目标)字段,服务从数据库中读取并进行一些检查。

当然,用户可以从活动中更改此目标。由于我将实现MVP架构模式。

我不确定要将服务放在哪里?它肯定不是视图。有什么建议吗?


1
你正在使用自定义的ContentProvider吗?如果是这样,请查看https://github.com/googlesamples/android-architecture/tree/todo-mvp-contentproviders/(以及https://github.com/googlesamples/android-architecture) - pskink
@pskink 不,我正在使用Realm数据库封装在一个DataManager中,我将使用Dagger注入到Service中。这是我的计划,至少目前是这样。谢谢!我会查看这些链接的。 - Georgi Koemdzhiev
1
无论如何,看看我发布的第一个链接,可能会有所帮助... - pskink
3
这项服务应该明确包含在模型中。然后将数据传递给Presenter,最终在View中显示。使用RxJava可以轻松实现这一点。 - Mikhail Kim
2
@GeorgiKoemdzhiev 我必须说这是一个很棒的问题。它一直困扰着我很长时间了。谢谢! - Sufian
显示剩余2条评论
3个回答

14
在干净的架构中,我假设你是使用MVP模式,有一个分离框架和业务逻辑的想法。这基本上就是正常Presenter所能实现的。在这种情况下,你处理的不是视图,但原则是相似的。当你可以将业务逻辑从Android代码中分离出来以便使用更加单一职责的类时,你不想把所有的业务或应用逻辑混合在一起。因此,我会说虽然它不是一个视图,但仍然应该有一个Presenter类型的类(可能更好地称为控制器或管理器)。
这个类将是一个POJO,控制你的服务的行为,可以使用标准的junit测试和服务模拟进行简单测试。这个类和服务可以放入自己的功能包中,并与后端模型以同样的方式交互。
因此,总之,它是你的应用程序另一个特性的角色,与其他特性(通常只是视图)并列。
希望这可以帮助。

非常感谢你,Alex!这真的很有帮助! :) - Georgi Koemdzhiev
1
理想情况下,您不应该传递上下文。由于上下文是 Android 代码,您希望将其保留在服务中,以使控制器更易于测试。不要让上下文成为上帝对象 ;) - MungoRae
1
@MungoRae,你能展示一些这种方法的样例代码吗? - Sufian
@MungoRae 不错的解决方案。这是一个非常简单而又很棒的解决方案!也许我当时评论的时候脑子不够清醒。:D - Sufian
考虑将一个Presenter注入到服务中。 - filthy_wizard
显示剩余2条评论

4

谢谢您的建议,Jose。我一定会看一下这篇文章! :) - Georgi Koemdzhiev

1

我处于同样的情况。最终,我决定做类似于以下的事情:

活动或片段超出了范围,它们不知道任何关于MVP的内容,但是我将使用事件总线(如Otto)发送信号/事件,所以:

我的一些Presenter类扩展了某种Presenter,不知道Android Context,但它们将具有一个MvpView接口,仅包括onAttachPresenter和onDetachPresenter。

扩展服务的类将具有一个Presenter属性,并实现一些MvpView接口,例如onSucess、onError、onStart、onComplete或类似的事件,以及Otto的相同事件(onSucessEvent、onErrorEvent、onStartEvent、onCompleteEvent)。

因此,当我需要做某事时,Activity或Fragment将启动服务,服务将“启动”或与Presenter通信,当Presenter成功完成后,将调用mvpView.onSuccess()并在SQLite中存储信息(也许是storeIO),最后服务将调用Otto并传递信号(其中没有任何数据),可能是onComplete。最终,UI(可能是片段)将捕获信号并从SQLite数据库中检索所有信息。

当onSuccess发生时,UI将显示最新和最好的数据。但是当onError发生时,至少会显示一些信息(如果您想要的话),告诉用户“出现了问题,但至少您可以看到一些东西”,无论是onSuccess还是onError都会在完成后调用onComplete。
不知道这是否是最佳解决方案,但在这种情况下,我认为我不会处理活动或片段生命周期,并且不关心保存实例并在用户旋转设备时恢复数据。它将始终获取DB内的最新数据,如果发生某些事情(没有互联网连接),则在接收到onComplete信号时,您可以至少显示一些内容。
我仍在思考一些事实:
- Presenter不会是单例类 - Presenter对Context一无所知,但对MyApplication类有所了解 - 如果对于一个屏幕(片段),您具有不同的服务和不同的onSuccessEvents会发生什么?只需使用某种操作作为ID来标识它们。 - 永远不要使Activity Fragment实现MvpView,您将不得不处理生命周期。

我明白了。这是一个很好的解决方案。我决定创建另一个名为Controller的类,它需要一个Context作为参数(我将不得不使用roboelectric测试该类),我的Presenter有这个类的实例,因此它不知道任何特定于android的代码,并且能够启动和停止服务 :)。至于Presenter的生命周期,在我的情况下并不太糟糕。 - Georgi Koemdzhiev
1
我不知道,但如果片段或活动启动服务,我认为这并没有什么不好。Android知道Android的事情,但MVP不知道。 - Nicolas Jafelle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接