我可以更新UI" tick"在UI线程的密集任务期间?

时间:2017-11-14 16:31:11

标签: android multithreading event-loop

我的应用程序有一项密集型任务,我目前正在UI线程上运行。大约需要15秒。因此,我真的需要在任务期间的战略要点更新UI,以便用户(和操作系统)不要认为应用程序已崩溃(停止响应)。

似乎有可能做这样的事情(伪代码):

void longTaskOnUIThread() {
    // Here I'm maintaining the sequence of steps as a sequence of statements
    // in one method, despite letting the UI catch its breath between steps.
    doAChunkOfTheTask();
    dispatchUIQueueMessage();
    int result = doSecondChunkOfTheTask();
    if (result < 3) {
        dispatchUIQueueMessage();
        doThirdChunkOfTheTask();
    }
}

void dispatchUIQueueMessage() {
    // Give the UI a chance to catch up a little:
    final MessageQueue queue = Looper.getMainLooper().mQueue; // not public
    // Don't block if no messages are ready.
    if (queue.hasMessages(...)) {
        Message msg = queue.next(); // Isn't public. :-(
        msg.target.dispatchMessage(msg);
    }
}

我的基础是Looper source code,但我不想使用未记录的功能,因为我无法依赖它们。如果有looper.dispatchNextMessageIfAny()方法,那将是理想的。

不重复:Android - updating UI during intensive task?类似,但是那个是关于从工作线程更新UI。这种方法在这里不起作用,因为只有UI线程可以更新UI,并且UI线程持续占用其密集型任务......除非明确花费一些时间来允许调度消息。

我意识到建议的方法是在后台线程上运行密集型任务,,这样可以让UI线程在需要时自由更新UI。这就是我通常做的事情,例如使用新的AsyncTasks和单独的服务。但这需要更多的控制流复杂性(编排),在每个任务完成后将控制权传回,并跟踪状态以确定哪个异步任务遵循哪个。

这个问题是调查可用的选项来在UI线程上执行操作,同时允许UI有时更新。了解选项的内容将有助于确定是否存在可以在UI线程上执行操作的某些情况。如果结论不是,那么这个问题的答案将帮助我知道为什么我有信心将我的时间投入另一个方向。

3 个答案:

答案 0 :(得分:0)

您可以使用runOnUiThread方法:

    SomeActivity.this.runOnUiThread(new Runnable() {
        public void run() {

            //update your ui here
        }
    });

您可以从工作线程

调用此方法

答案 1 :(得分:0)

从这里的答案和我已经完成的研究来看,似乎答案是,你不能在UI线程上做某事,告诉用户界面更新一点&#34;不会产生控制流(即,在没有从正在执行的方法返回的情况下进行UI更新)。

这有助于我更自信地做出决定,我需要将控制流/编排移动到单个更大的服务任务,而不是让UI线程在几个较小的服务任务之间进行协调。

答案 2 :(得分:-1)

  

我的应用程序有一项密集型任务,我目前正在UI线程上运行

由于名称表示UI线程用于UI。如果你在那个线程上做得很重,那么你肯定做错了。

  

但这需要更多的控制流复杂性(编排),

没有。它只需要您使用AsyncTask进行相同的工作量。或者,您可以使用RxJava。或者只是简单的EventBus。它并不比通常复杂。

  

在每个任务完成后将控制权传回

为什么你首先将控制权交给计算线程?控件应始终保持在UI线程上。