是否有任何开发模式可以替代网络请求的 IntentService?

Posted

技术标签:

【中文标题】是否有任何开发模式可以替代网络请求的 IntentService?【英文标题】:Is there any development pattern that can replace an IntentService for network requests? 【发布时间】:2015-09-29 13:29:08 【问题描述】:

在我与同事一起开发的当前应用程序中,我们使用 IntentServices 和内部的 Volley 调用来处理 RESTful API 网络请求。这只是简单的 JSON 字符串数据,以及一些小图像。

对于那些有处理网络请求经验的人,我的问题是:有没有更合适或更清洁的方法可以实现?

据我了解,使用 IntentService 的优势在于它在主线程之外的后台运行,并且通常是 android 操作系统杀死的最后一件事。缺点是 IntentServices 是按顺序运行的。

我已经阅读了很多关于 RxJava 和 Retrofit 的内容,并且觉得通过这种组合可以更好地满足我们的需求。改造本身可能就足够了,但我真的很感激一些第三方的见解。

【问题讨论】:

您可能想探索 Android Volley 库:developer.android.com/training/volley/index.html @AADTechnical 这是有趣的部分,我们在 IntentServices 中使用 Volley。 我肯定会推荐 Rxjava 和改造 @r7v 您认为该组合更有优势吗? @RyanSimon 为什么不使用普通服务?至于 RXJava,要掌握它有点棘手,但值得花时间投资,因为它提供了令人难以置信的灵活性。绝对使用 Retrofit 来发出您的网络请求并序列化/反序列化任何响应。 Retrofit 为 Gson 提供了一个准“包装器”,这使得从网络请求返回的 JSON 对象的序列化非常容易。 【参考方案1】:

我的一般经验法则是:

如果网络 I/O 应该在 1 秒以下,并且您不介意它没有运行到完成,那么任何异步选项都应该没问题。

如果网络 I/O 应该超过一秒,或者您确实想增加它运行完成的几率,请使用 Service。是否使用IntentService 或其他一些Service 实现取决于您,但您希望有一个Service 作为您正在工作的操作系统的指示器,因此它不会终止您的进程一旦您的应用程序移至后台,就可以快速进行。请记住,“移至后台”并不总是由用户直接发起的,因为来电等也会将您移至后台。

如果网络 I/O 需要超过 15 秒,你不仅需要使用Service,还需要考虑使用WakeLock(通过我的WakefulIntentService,或@ 987654328@,或您自己精心管理的WakeLock),也可能是WifiLock。 15 秒是设置中的最短自动屏幕关闭时间,这是该数字的来源。

考虑到所有这些:

缺点是 IntentServices 是按顺序运行的。

我将其翻译为“IntentService 有一个用于处理请求的线程”。这是真实的。如果您需要Service 并且需要并行处理,请创建您自己的Service。当您没有出色的工作时,请务必致电stopSelf()

我已经阅读了很多关于 RxJava 和 Retrofit 的内容,并且觉得通过这种组合可以更好地满足我们的需求

这与您是否使用Service 无关。只是不要尝试从IntentService 执行异步操作(例如,使用Callback 的改造调用),因为您违背了IntentService 的目的(向操作系统表明您正在工作)。因此,从 IntentService 开始,您将使用 Retrofit 的同步 API,而不是 Callback

【讨论】:

这是一个很好的解释,谢谢。只是为了确保我理解用例:我想在将网络结果与我的数据库同步时使用服务(因为我真的希望它能够正确完成),但如果我只是请求一些包含博客文章文本的 JSON(或任何小到足以再次快速获取的数据),为此麻烦设置服务并不重要。这有意义吗? @RyanSimon:这似乎是合理的。我的典型类比是 Twitter 客户端。你真的不需要下载头像的服务。您可能会使用服务来下载时间线,但这主要是如果您让它们保持离线同步,并且您定期更新本地数据库(AlarmManagerSyncManager 等)。即使发布推文,您也可能会跳过该服务。但是设置一个新的 Twitter 帐户,或任何可能处理附件的操作(例如,上传图片作为推文的一部分)都应该使用服务。【参考方案2】:

仅使用 IntentServices 来执行一个简单的网络请求,IMO,实在是太多了。如果您不想使用库,或者您更喜欢使用 Retrofit、Volley...(我会推荐 Retrofit),则应该使用 AsyncTask。 IMO、Services 或本例中的 IntentService 旨在执行长时间的后台任务。

【讨论】:

是什么让你说 IntentService 对于网络请求来说太多了?那是不好的做法呢? “仅使用 IntentServices 来执行网络请求太多了”——这完全取决于网络请求是什么。例如,下载大文件与下载 Twitter 头像不同。 True @CommonsWare,我会更新答案。 IMO,我只在需要执行一组请求或执行请求并持久化数据时才使用 IntentService……要执行单个请求,我更喜欢使用更易于集成的东西,例如 Retrofit 或其他工具。跨度> 【参考方案3】:

真正的问题是:您加载数据是为了在前台填充 Activity 还是为了进行后台工作,即使没有 UI 可见?

对于后台工作,服务是可行的方法。如果你依赖 Volley 的线程管理,你甚至不需要 IntentService。

对于前台工作,请考虑直接在 Activity/Fragment 中使用 Loaders、Volley 或 Rxjava 调用。

【讨论】:

是的,我们主要使用网络请求来更新 UI

以上是关于是否有任何开发模式可以替代网络请求的 IntentService?的主要内容,如果未能解决你的问题,请参考以下文章

是否有任何替代方法来实现 WebRTC SFU,只有 1 个上传流?

替代时钟应用程序

GOF 单例模式是不是有任何可行的替代方案?

是否有任何有价值的 CSLA 替代品?

可以替代面向对象设计模式的功能或动态技术示例

是否有任何替代工具可以替代 HTMLUnit for Android?