【问题标题】:Does a runnable in a service run on the UI thread服务中的可运行对象是否在 UI 线程上运行
【发布时间】:2019-03-21 08:22:08
【问题描述】:

在 Android 中,当我在服务中创建一个可运行对象并运行它时,虽然我意识到它在自己的线程中运行,但这个线程在某种程度上是 UI 线程的一部分吗?也就是说,如果runnable执行了很长的进程,会不会影响UI?

编辑:

private class SomeRunnable implements Runnable
{
  @Override
  public void run()
  {
    try
    {

    }
  }
}

SomeRunnable runnable = new SomeRunnable();
(new Handler()).postDelayed(runnable, 1000);

【问题讨论】:

  • 取决于你如何运行它。
  • 您的假设“......虽然我意识到它在自己的线程中运行......”是不正确的。 Runnable 可以在任何地方运行,这取决于你在哪里运行它。例如,如果您只是在您的Service 中创建一个Handler,然后使用Handler 发布您的Runnable,它将在主(UI)线程上运行。
  • 感谢您的编辑。使用此代码,您的 Runnable 正在主 (UI) 线程上运行。如果此Runnable 需要很长时间,您将面临应用程序因 ANR(应用程序无响应)错误而被强制关闭的风险。
  • 在 AsyncTask 中运行它会更好还是我仍然会遇到同样的问题?
  • 如果您只想在单独的线程中运行Runnable,则不需要AsyncTask。就这样做:new Thread(new SomeRunnable()).start();

标签: android runnable


【解决方案1】:

文档:

服务在与其所在的应用程序相同的进程中运行 声明并在该应用程序的主线程中,

不同的线程:

Thread t = new Thread(new MyRunnable());
t.start();

UI/服务线程:

Handler h = new Handler();
h.post(new MyRunnable());

【讨论】:

  • 但那是指服务。我的问题是关于从服务启动可运行文件。
  • @AndroidDev 第一段代码在单独的线程上启动Runnable与 UI 线程完全无关。第二段代码在运行服务的同一线程上运行Runnable,它将影响UI线程
  • 我用 Handler 启动它,所以根据你的说法,它必须在 UI 线程上运行。
  • @AndroidDev 在处理程序的情况下,它将在执行new Handler() 的线程上运行,就像您在服务的onBind() 中创建处理程序一样,该处理程序现在指向服务线程。
【解决方案2】:

不,它不是UI thread 的一部分,我假设Runnable 是指通过调用start() 执行的新线程。

无论您在 serviceactivity 中启动新的 Thread,它都将成为 UI 线程的一部分(除非您调用类似 join() 的名称)

编辑

由于您使用Handler 运行Runnable 对象,因此这取决于您初始化您的handler 的位置。服务运行在main thread,因此在服务或活动中初始化处理程序将使代码发布到UI thread

注意,每个线程都需要一个 Handler 对象;所以避免每次都创建一个新的,例如应避免使用(new Handler()).postDelayed(runnable, 1000);,而应避免使用handler.postDelayed(runnable, 1000);,其中handler 是在您的服务/活动类中初始化的实例变量

【讨论】:

  • User117 似乎另有说明。你确定吗?
  • 您的问题需要进一步澄清,Runnable 到底是什么意思。我清楚地提到了,如果您通过调用start() 开始一个新的Thread,它将与UI Thread 不同
  • 查看我在原始帖子中添加的代码。没有开始。
  • 我从未听说过使用 start 运行 Runnable。我只熟悉 runOnUiThread 和使用 Handler。但是,我熟悉使用 start() 启动线程。
  • 我不使用 (new Handler())。我只是发布它来表明我使用了一个处理程序。事实上,我只创建一次处理程序,它是一个私有成员。
【解决方案3】:

您提交给处理程序的可运行文件将始终在 UI 线程上执行,因为服务不会在不同的进程或线程上生成,但您是 UI 线程的一部分

【讨论】:

    【解决方案4】:

    默认情况下,服务在 UI 线程中运行。但这取决于服务类型和服务属性以及您发布可运行文件的方式。我认为您使用默认方案,您的可运行文件将在 UI 线程上执行并阻止它。

    如果你展示你如何发布可运行和创建服务的代码,我可以给你确切的答案。

    您可以使用以下代码从可运行文件中检查线程类型:

    if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
        // On UI thread.
    } else {
        // Not on UI thread.
    }
    

    目前还不清楚。如果你在 UI 线程上执行“new Handler()”,那么 runnable 将在 UI 线程上执行。如果您在另一个带有 looper 的线程上执行“new Handler()”,那么 runnable 将在该线程上执行。我认为您的可运行文件有 99% 的可能性将在 UI 线程上执行。你为什么不把我的代码放在runnable中并检查它的执行位置?

    【讨论】:

    • 我在这里看到了相互矛盾的回复。有些人似乎说是,有些人说不是。
    • @AndroidDev 是的,因为“创建Runnable”有不同的方法。如果您将使用用于“创建Runnable”的代码更新您的帖子,那么我们可能会给您一个更好的答案。
    • 查看我对您问题的评论。 Runnable 在主 (UI) 线程上运行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 2011-08-06
    • 1970-01-01
    • 2016-02-10
    • 2011-09-02
    相关资源
    最近更新 更多