因此,如果我有5个异步任务正在运行并且取消了它们,则UI会冻结一些,但是如果我做了20个asyncTasks并取消了它们,则UI会冻结一段时间。我的问题是,asyncTask.cancel(true)方法是否昂贵?这样我的用户界面会冻结吗?我注意到,当我不打电话取消时,我的UI不会冻结。无论如何,我可以防止UI冻结吗?我尝试将.cancel(true)方法放入自己的线程中,但这没有帮助。

这里有一些代码。

     //could be as little as 1 or could be 20
    for( AsyncTask asyncTask : asyncTasks )
    {
        if ( asyncTask != null )
        {
            //seems to block UI for a bit if there are a lot of calls
            asyncTask.cancel( true );
        }
    }

最佳答案

您的任务是否检查isCancelled()函数中的doInBackground()

AsyncTask的目的是在后台快速运行(即计算上很短的任务),并将结果发布到UI线程。这意味着,当您调用asyncTask.cancel(true);时,不是在UI线程上调用 onPostExecute,而是在UI线程上调用onCancelled

由于“取消”是在UI线程上调用的,因此,如果您的线程处于紧密循环中,并且不对任何全局变量进行任何检查或取消请求(例如检查isCancelled),则可能要花费一些时间对于底层API来清理线程(正确结束/取消线程而线程本身不会结束),“时间”就是您遇到的UI“暂停”。

为了减轻这种情况,只需在doInBackground函数中检查isCancelled函数:

// simple example function:
protected Void doInBackground (Void... params) {
    for(int i=0; i < 65535; ++i) {
        if (isCancelled()) { break; } // exit loop on cancel request
    }
    return null;
}


在此AsyncTask中,如果我们再调用asyncTask.cancel(true);,则循环将在下次检查isCancelled时中断,并且UI线程可以继续与等待循环完成其迭代(因此“暂停” UI直到线程已完成)。

希望能对您有所帮助。

10-08 08:21
查看更多