Runnables会阻止UI线程吗?

时间:2017-08-21 07:29:12

标签: java android multithreading runnable ui-thread

我试图了解UI线程的事件队列是如何工作的。我试图运行可以分解成许多部分的代码但不幸的是它必须在UI线程上运行。因此,为了不阻止UI线程并接收ANR,我想知道我是否可以在许多Runnable个对象中破坏该代码并使用另一个线程中的runOnUiThread运行它们。

我的问题是,这会阻止UI线程吗?例如,如果我有一段代码肯定会在5秒内运行并且我将这些代码分解为,那么让我们说1000 Runnable个对象,并将它们添加到UI线程的事件队列中,其他事件是否会被它们之间的UI线程处理?

编辑:我认为如果上述解释令人困惑,我发现了一种更好的表达方式。

  • 1000 Runnable个对象只是一个例子,在我想要的实际代码中最多只有10个。
  • 基本上,我想要10个Runnable个对象,每个对象在UI线程上初始化一个广告网络。我希望这些Runnable对象一个接一个地运行,而不是并行运行。此外,我希望UI线程能够在运行这些对象之间处理其他事件,以便在运行所有10个run方法时,我不会获得ANR超过5秒。

注意:我不知道为什么必须在UI线程上初始化广告网络,但它必须,否则应用程序崩溃。它还说明了一些网络'的SDK'初始化必须在UI线程上发生的文档。这就是为什么我需要在UI线程上一个接一个地运行它们,我不能在后台并行运行它们。 此外,该应用程序实际上是一个OpenGl游戏,因此运行Runnable对象的调用将来自GL线程,而不是主线程,因此它们将被添加到事件队列中,而不是立即执行。 / p>

4 个答案:

答案 0 :(得分:1)

嗯,Runnable中的runOnUiThread只是Main Thread中的操作。

想象一下像

这样的简单动作
textView.setText("example");

将阻止主线程持续5 ms。通常你不会看到它。

现在假设你有5次相同的1000次操作。每个块Main Thread持续5毫秒。简单计算5ms * 1000 = 5000ms = 5秒。所以它会永久阻止Main Thread。但是如果你有10个操作,你将只阻止50毫秒,换句话说它只有1%的负载,你感觉不到。

所以可能的调用量取决于View的大小,渲染的难度以及设备的速度。

P.S。对于AsyncTask的专家 - runOnUiThreadAsyncTask之间没有真正区别,因为那些Runnables将以同样的方式在Main Thread中执行。

即使我在Activity的创建方法中做同样的事情也会阻止UI

答案 1 :(得分:1)

是。在UI线程上执行的Runnable将阻止主线程。

检查以下方法是否对您有用。

  1. 使用requestHandler
  2. 中的Handler创建Looper
  3. 为主线程创建一个带Looper的处理程序:responseHandler并覆盖handleMessage方法
  4. {li> post Runnable 上的requestHandler任务
  5. Runnable内部任务,请致电sendMessage
  6. 上的responseHandler
  7. sendMessage handleMessage responseHandler Message /* Handler */ Handler requestHandler = new Handler(Looper.getMainLooper()); final Handler responseHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { //txtView.setText((String) msg.obj); Toast.makeText(MainActivity.this, "Adwork task is completed:"+(String)msg.obj, Toast.LENGTH_LONG) .show(); } }; for ( int i=0; i<10; i++) { // Start Adwork task Runnable myRunnable = new Runnable() { @Override public void run() { try { /* Your business logic goes here */ // Send some result after computation String text = "" + (++rId); Message msg = new Message(); msg.obj = text.toString(); responseHandler.sendMessage(msg); System.out.println(text.toString()); } catch (Exception err) { err.printStackTrace(); } } }; requestHandler.post(myRunnable); } 次结果调用。{/ 1}
  8. flatMap获取属性并对其进行处理,更新用户界面
  9. 示例代码:

       tl
        .flatMap { p => 
           p.from -> (p.amount, 0),
           p.to -> (0, p.amount)
        }.groupBy(_._1)
         .mapValues { tuples => 
            tuples.foldLeft((0,0)) { case ((a,b), (_, (c,d))) => (a+c, b+d) } 
         }
    

    有用的文章:

    handlerthreads-and-why-you-should-be-using-them-in-your-android-apps

    android-looper-handler-handlerthread-i

答案 2 :(得分:0)

是的,如果你在Ui线程中运行大量操作,你会觉得动画会停止或启动快门。它还取决于设备的速度。

我建议你将代码分为两部分。一个可以在后台完成,另一个需要Ui线程并在AsyncTask中执行它们。

使用doInBackgroud方法执行繁重操作,使用onPostExecute更新UI。

注意:如果您将代码分成1000个线程并在一瞬间运行它们,那么您可能会遇到设备队列限制。 (将它们分成10-50个部分。)

答案 3 :(得分:0)

您要找的是AsyncTask

这些设计用于执行一些后台处理,而UI线程继续。它不会阻止UI,也不会导致ANR。

在AsyncTask中,是一种onPostExecute方法,允许您将结果发布回UI。所以它并没有完全脱离UI线程。在后台处理期间连接onProgressUpdate