【问题标题】:Application threads vs Service threads应用程序线程与服务线程
【发布时间】:2011-02-07 16:00:11
【问题描述】:

将冗长的网络访问代码放置在活动中的线程或服务中的线程中的优点/缺点是什么?它将如何影响申请?我正在编写一个流式音频播放器,从我目前所读的内容来看,将代码放入服务中最终仍会阻塞应用程序,因此需要一个新线程,有谁知道放置这段代码是否更有意义在服务中。

【问题讨论】:

    标签: android multithreading service media-player


    【解决方案1】:

    是的,服务中的阻塞操作仍然会阻塞应用程序。尽管第一次出现,服务并不仅仅用于在后台运行任务。它们用于运行具有独立于 Activity 生命周期的生命周期的任务(IE,它们可能会在 Activity 关闭后继续运行)。

    一个在Activity启动时启动,在Activity结束时结束的Service是没用的。

    在您正在流式传输音频的情况下,即使在用户关闭 Activity 后,您也可能希望流式传输音频,在这种情况下,您应该使用服务,但您仍然需要一个线程(或 AsyncTask)用于阻塞任务。

    【讨论】:

    • 谢谢,我就是这么想的。在一个相关的话题上,至少在模拟器中,在我启动流媒体播放器之后,即使我按下后退按钮,它也会继续播放。我假设当活动不再在前台时它会停止......是因为新线程还是它会播放,直到 android 杀死应用程序。
    • 是的,线程将一直运行,直到 Android 将其杀死。如果您希望它停止,请实现某种“活动”标志并在您的 onDestroy() 方法中将其设置为 false。
    • 另请注意,Activity 中的线程会在配置(读取:方向)更改时被破坏!这不适用于Service s 中的线程。
    • Activity 中的线程在配置更改期间根本不会被破坏。但是,它们可能具有对旧 Activity 的本地引用,这可能是个问题。
    • 他们可能有本地参考,这可能是您所说的问题? @synic?如果是这种情况,那么......我们应该确保 UI(活动)对于仍在运行并希望访问它的服务仍然处于活动状态。正确的?否则,错误应该出现在 try & catch 语句中。
    【解决方案2】:

    根据我的经验(1 年以上的 Android 开发经验),在服务或活动中运行新线程没有区别。 尽量不要在新线程中保留对 Activity 的引用 - 使用应用程序上下文。

    此外,服务的生命周期根本没有帮助,因为不能保证调用某些方法:(

    唯一的区别可能是服务可以在不完全破坏应用程序的情况下被破坏 - 因此可能破坏新线程。 为什么是潜在的?因为在实际方面,这不会发生。应用程序总是被杀死而在此之前没有杀死服务,意思是:本地服务机制没用!!!

    远程服务是一个不同的讨论 - 我只是指“我应该在哪里运行一个新线程?”。

    祝你好运!!!

    【讨论】:

    • 您能否给出需要在服务中运行新线程而不是在活动中运行新线程来完成相同任务的情况?
    • @committedandroider 假设您有一个浏览器应用程序,用户选择下载 1 GB 的文件。用户不会让您的浏览器应用程序保持打开状态并等待文件下载。他将简单地开始下载并退出应用程序。在这种情况下,如果从 Activity 派生的线程将不再运行,因此您需要从 Service 派生一个线程。
    • @committedandroider 你是对的。你问这个问题已经很久了。但最近我加入了 SO 并且了解了服务和线程,所以我更愿意回答你的问题。
    【解决方案3】:

    区别在于系统如何管理您的application process lifecycle。运行线程不会影响应用程序进程的生命周期,但服务会。

    为了确定在内存不足时应该终止哪些进程,Android 会根据其中运行的组件和这些组件的状态将每个进程放入一个重要性层次结构。如果您的应用没有可见的活动或前台服务但有后台服务,则它被归类为服务进​​程,并且在优先级较低的缓存进程中保持活动状态> 存在。但如果应用既没有可见的活动/片段、前台服务也没有后台服务,则它被归类为缓存进程,并且可以随时终止以释放系统资源,无论它是否有正在运行的线程与否。

    但不要急于创建后台服务,现在有更现代的方法来处理后台任务。考虑下面和background processing guide 中描述的替代解决方案,并牢记与后台服务相关的所有限制。

    如果一个线程执行一个任务,结果只有一个活动需要,线程生命周期应该绑定到活动。在这种情况下,不需要任何服务。所谓的immediate tasksViewModel + Kotlin Coroutines + ViewModelScope 是处理它的好方法,有关不同类型的后台任务的更多详细信息,请参阅Guide to background processing

    如果无论用户是否关闭您的应用程序都应该完成任务并且不需要立即执行它,请考虑使用WorkManager,这是处理此类deferred tasks 的好方法。详情请见Android Work Manager vs Services?

    否则,如果您有一个生命周期未绑定到活动/片段的即时任务,那么foreground service 可能是最佳选择,尤其是在音频播放器的情况下。有一些limitations从Android 8开始考虑后台服务,系统会在应用关闭后几分钟内停止应用的后台服务,所以不适合长时间运行的任务。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多