详解Android进程和线程

2019-12-10 17:56:15王振洲

为解决此问题,Android 提供了几种途径来从其他线程访问 UI 线程。以下列出了几种有用的方法:

Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
例如,您可以通过使用 View.post(Runnable) 方法修复上述代码:

public void onClick(View v) {
  new Thread(new Runnable() {
    public void run() {
      final Bitmap bitmap = loadImageFromNetwork("http://www.easck.com/pre>
	
	

现在,上述实现属于线程安全型:在单独的线程中完成网络操作,而在 UI 线程中操纵 ImageView。

但是,随着操作日趋复杂,这类代码也会变得复杂且难以维护。 要通过工作线程处理更复杂的交互,可以考虑在工作线程中使用 Handler 处理来自 UI 线程的消息。当然,最好的解决方案或许是扩展 AsyncTask 类,此类简化了与 UI 进行交互所需执行的工作线程任务。

使用 AsyncTask

AsyncTask 允许对用户界面执行异步操作。它会先阻塞工作线程中的操作,然后在 UI 线程中发布结果,而无需您亲自处理线程和/或处理程序。

要使用它,必须创建 AsyncTask 子类并实现 doInBackground() 回调方法,该方法将在后台线程池中运行。要更新 UI,必须实现 onPostExecute() 以传递 doInBackground() 返回的结果并在 UI 线程中运行,这样,您即可安全更新 UI。稍后,您可以通过从 UI 线程调用 execute() 来运行任务。

例如,您可以通过以下方式使用 AsyncTask 来实现上述示例:

public void onClick(View v) {
  new DownloadImageTask().execute("http://www.easck.com/** The system calls this to perform work in a worker thread and
   * delivers it the parameters given to AsyncTask.execute() */
  protected Bitmap doInBackground(String... urls) {
    return loadImageFromNetwork(urls[0]);
  }

  /** The system calls this to perform work in the UI thread and delivers
   * the result from doInBackground() */
  protected void onPostExecute(Bitmap result) {
    mImageView.setImageBitmap(result);
  }
}