有没有一种开发模式可以替代IntentService处理网络请求?

9
在我和同事正在开发的当前应用程序中,我们正在使用IntentServices和Volley调用来处理RESTful API网络请求。它只是一些简单的JSON字符串数据和一些小图片。
对于那些经验丰富的网络请求处理人员,我的问题是:是否有更适合或更清晰的实现方法?
据我所知,使用IntentService的优点是它在后台运行而不是在主线程上运行,并且通常是Android操作系统终止的最后一件事。缺点是IntentServices按顺序运行。
我已经阅读了很多关于RxJava和Retrofit的文章,感觉我们的需求可以通过这种组合更好地满足。Retrofit本身可能已经足够了,但我真的很希望得到一些第三方的见解。

你可能想要探索Android Volley库:https://developer.android.com/training/volley/index.html - AADProgramming
每次我开始一个带有网络功能的应用程序时,我都会考虑使用Retrofit和GSON。Retrofit内置支持GSON。Rxjava使并发处理更加容易。Retrofit还支持rxjava,您可以将响应作为对象或可观察对象(rxjava)获取。我想指出的一件事是,Rxjava具有陡峭的学习曲线,如果您计划开始使用Rxjava,您必须考虑这一点。 - rahul.ramanujam
@r7v 感谢你的反馈,我非常欣赏。听起来 Retrofit 和 RxJava 是明智的选择。 - Ryan Simon
说“网络请求”几乎毫无意义。网络I/O的模式在很大程度上取决于该网络I/O的性质。例如,实现VOIP客户端所做的事情与为电子邮件客户端所做的事情不同。无论是Service(无论是IntentService还是其他服务)都解决了与Retrofit解决的问题正交的特定问题,而Retrofit解决的问题与RxJava解决的问题也是不同的。 - CommonsWare
@CommonsWare 非常好的观点。我应该更具体一些。我们正在进行RESTful API调用(简单的JSON字符串数据),有时会下载/上传小图像到我们的服务器。 - Ryan Simon
显示剩余4条评论
3个回答

22

我的经验法则是:

  • 如果网络I/O时间应该在一秒内,并且不介意它是否能完成,任何异步选项都可以。

  • 如果网络I/O时间应该超过一秒,或者您真的想增加它能够顺利运行的机会,使用Service。无论您使用IntentService还是其他Service实现,都取决于您,但是您需要拥有一个Service作为操作系统的指示器,告诉它您正在工作,这样一旦您的应用程序移至后台,它就不会那么快地终止您的进程。请记住,“移至后台”并不总是由用户直接发起的,因为来电等也会将您移至后台。

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

有了这些想法:

缺点是IntentServices按顺序运行。

我的翻译是“IntentService有一个处理请求的单个线程”。这是正确的。在需要Service且需要并行处理的情况下,请创建自己的Service。只要确保没有未完成的工作,就调用stopSelf()

我一直在阅读关于RxJava和Retrofit的文章,并认为我们可以更好地满足需求。

这与您是否使用 Service 无关。只要不要尝试从 IntentService 中进行异步操作(例如,使用 Callback 的 Retrofit 调用),因为这会打败 IntentService 的目的(向操作系统指示您正在执行工作)。因此,从 IntentService 中,您将使用 Retrofit 的同步 API,不带 Callback


这是一个很好的解释,谢谢。只是为了确保我理解使用情况:当将网络结果与我的数据库同步时(因为我真的希望它能正确完成),我想要使用服务,但如果我只是请求一些包含博客文章文本(或任何足够快速获取的小数据),那么设置服务并不重要。这有意义吗? - Ryan Simon
1
@RyanSimon:这看起来很合理。我的典型比喻是Twitter客户端。你真的不需要一个用于下载头像的服务。如果你要将时间轴同步离线,并定期更新本地数据库(AlarmManagerSyncManager等),那么你可能会使用一个用于下载时间轴的服务。即使发布推文,你也可以跳过服务。但是设置新的Twitter帐户或任何可能涉及附件的操作(例如,将图片作为推文的一部分上传)应该使用服务。 - CommonsWare

0

仅仅为了执行一个简单的网络请求就使用IntentServices,我认为有点过头了。如果您不想使用库或者更喜欢使用Retrofit、Volley等,请使用AsyncTask。(我建议您使用Retrofit) 在我的观点中,服务或者在这种情况下,是指IntentService是用来执行长时间后台任务的。


你为什么说IntentService对于网络请求来说太多了?它的哪些方面是不好的实践? - Ryan Simon
仅仅为了执行一个网络请求而使用IntentServices是过度的 - 这完全取决于网络请求的内容。例如,下载大文件与下载Twitter头像是不同的。 - CommonsWare
True @CommonsWare,我会更新回答。 在我看来,只有当需要执行一组请求或执行请求并持久化数据时,才会使用 IntentService... 执行单个请求时,我更喜欢使用更简单易于集成的工具,例如 Retrofit 或其他工具。 - Sandro Machado

0

真正的问题是:您是否加载数据以填充前台活动或进行后台工作,即使没有可见的UI?

对于后台工作,Service是最好的选择。如果您依赖于Volley的线程管理,则甚至不需要IntentService。

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


是的,我们主要使用网络请求来更新用户界面。 - Ryan Simon

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