一个服务中的可运行对象是否在UI线程上运行?

4
在Android中,当我在服务中创建并运行一个可运行对象时,尽管我意识到它在自己的线程中运行,但这个线程是否与UI线程有关?换句话说,如果可运行对象执行了一个长时间的过程,会影响UI吗?
编辑:
private class SomeRunnable implements Runnable
{
  @Override
  public void run()
  {
    try
    {

    }
  }
}

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

取决于你如何运行它。 - njzk2
1
你的假设“...虽然我知道它在自己的线程中运行...”是不正确的。一个Runnable可以在任何地方运行,这取决于你在哪里运行它。例如,如果你只是在你的Service中创建一个Handler,然后使用Handler发布你的Runnable,它将在主(UI)线程上运行。 - David Wasser
感谢您的编辑。使用此代码,您的“Runnable”将在主(UI)线程上运行。如果此“Runnable”需要很长时间,则可能会导致应用程序出现ANR(应用程序无响应)错误而被强制关闭。 - David Wasser
我是否最好在AsyncTask中运行它,还是最终仍然会遇到同样的问题? - Johann
1
如果你只想在单独的线程中运行Runnable,那么你不需要使用AsyncTask。只需执行以下操作:new Thread(new SomeRunnable()).start(); - David Wasser
4个回答

11

文档:

服务与声明它的应用程序在同一进程中运行,并且在该应用程序的主线程中运行。

不同的线程:

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

用户界面/服务线程:

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

但是那是关于服务的。我的问题是关于如何从服务中启动可运行程序。 - Johann
2
@AndroidDev 第一段代码在单独的线程上启动了一个“Runnable”,与UI线程完全无关。第二段代码在服务运行的同一线程上运行“Runnable”,并且它会影响UI线程 - S.D.
我正在使用Handler启动它,所以根据您的说法,它必须在UI线程上运行。 - Johann
2
在处理程序的情况下,它将在执行new Handler()的线程上运行,就像您在服务的onBind()中创建处理程序一样,该处理程序现在指向服务线程。 - S.D.

2
不,它不是UI线程的一部分。我猜你所说的“Runnable”是指通过调用“start()”执行的新线程。
无论您在服务或活动中启动新线程,它都不会成为UI线程的一部分(除非您调用像“join()”这样的内容)。
编辑
由于您正在使用Handler运行Runnable对象,所以它取决于您在哪里初始化handler。服务在主线程中运行,因此在服务或活动中初始化处理程序将使代码被发布到UI线程。
请注意,每个线程需要一个单独的Handler对象;因此,避免每次创建一个新的Handler对象,例如应避免“(new Handler()).postDelayed(runnable, 1000);”,而是使用已在服务/活动类中初始化的实例变量“handler.postDelayed(runnable, 1000);”。

User117似乎表示不同意。你确定吗? - Johann
你的问题需要更多的澄清,你所说的“Runnable”具体是什么意思。我已经很清楚地提到了,如果你通过调用“start()”来启动一个新的“Thread”,它将与“UI Thread”不同。 - iTech
请查看我在原始帖子中添加的代码。没有开始。 - Johann
我从未听说过使用start来运行Runnable。我只熟悉runOnUiThread和使用Handler。但是,我熟悉使用start()来启动线程。 - Johann
我不使用(new Handler())。我只是发布它来展示我使用Handler。实际上,我只创建一次处理程序,它是一个私有成员。 - Johann

0

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

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

您可以使用以下代码检查可运行程序的线程类型:

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

仍然不太清楚。如果在UI线程上执行“new Handler()”,则可运行对象将在UI线程上执行。如果在具有looper的另一个线程上执行“new Handler()”,则可运行对象将在该线程上执行。我认为你的可运行对象有99%的概率在UI线程上执行。为什么不把我的代码放在可运行对象中,然后检查它在哪里执行?


我看到这里发布了一些相互矛盾的回复。有些人似乎说是,而其他人则说不是。 - Johann
@AndroidDev 是的,因为有不同的方法来“创建Runnable”。如果您更新帖子并附上您用于“创建Runnable”的代码,那么我们可能会给您更好的答案。 - David Wasser
请看我的评论,那个Runnable在主线程(UI线程)上运行。 - David Wasser

0

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


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