本文最后更新于:1 个月前

当应用组件启动且该应用未运行任何其他组件时,Android 系统会使用单个执行线程为应用启动新的 Linux 进程。默认情况下,同一应用的所有组件会在相同的进程和线程(称为“主”线程)中运行。如果某个应用组件启动且该应用已存在进程(因为存在该应用的其他组件),则该组件会在此进程内启动并使用相同的执行线程。但是,可以安排应用中的其他组件在单独的进程中运行,并为任何进程创建额外的线程。

进程

各类组件元素(<activity>, <service>, <receiver>, <povider>)的清单文件条目均支持 android:process 属性,该属性可指定该组件应在哪个进程中运行。

<application> 元素也支持 android:process 属性,用来设置适用于所有组件的默认值。

线程

工作线程

从其他线程访问界面线程的方法:

  • Activity.runOnUiThread(Runnable)
  • View.post(Runnable)
  • View.postDealyed(Runnable, long)

上述方法会增加后期维护难度,如果要通过工作线程处理更复杂的交互,可以考虑在工作线程中使用 Handler 处理来自界面线程的消息。当然最后的解决方案或许是扩展 AsyncTask 类,此类可简化与界面进行交互所需执行的工作线程任务。

如何避免应用无响应(ANR)

为耗时较长的操作创建工作线程的最有效方法是使用 AsyncTask 类。只需扩展 AsyncTask 并实现 doInBackground() 方法即可执行相应操作。要向用户发布进度变化,可以调用 publishProgress(),它会调用 onProgressUpdate() 回调方法。通过 onProgressUpdate()(在界面线程中运行)的实现,您可以向用户发送通知。例如:

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
    // Do the long-running work in here
    protected Long doInBackground(URL... urls) {
        int count = urls.length;
        long totalSize = 0;
        for (int i = 0; i < count; i++) {
            totalSize += Downloader.downloadFile(urls[i]);
            publishProgress((int) ((i / (float) count) * 100));
            // Escape early if cancel() is called
            if (isCancelled()) break;
        }
        return totalSize;
    }

    // This is called each time you call publishProgress()
    protected void onProgressUpdate(Integer... progress) {
        setProgressPercent(progress[0]);
    }

    // This is called when doInBackground() is finished
    protected void onPostExecute(Long result) {
        showNotification("Downloaded " + result + " bytes");
    }
}

要执行此工作线程,只需创建一个实例并调用 execute() 即可:
new DownloadFilesTask().execute(url1, url2, url3);


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

Kotlin的学习(一)——开始 上一篇
Intent 下一篇