本文最后更新于: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 协议 ,转载请注明出处!