在Android的子线程去更新UI的内容,会导致不确定的异常。

因为Android有个模式是,单一线程模型:Android UI工具箱(toolkit)不是一个线程安全的,并且它总是被放在主线程上操作。

public void onClick(View v) {  new Thread(new Runnable() {    public void run() {      Bitmap b = loadImageFromNetwork();      mImageView.setImageBitmap(b);    }  }).start();}

首先,从上面代码看上去好像非常完美,因为它不会阻塞UI线程,不幸的是,它违背了单一线程模型:Android UI工具箱(toolkit)不是一个线程安全的,并且它总是被放在主线程上操作。

这个ImageView被一个工作线程操作,这导致非常不可思议的问题。跟踪和修复这样一个bug很难并且也耗时。 Android提供了几种从其他线程访问主线程的方式:
  1. Activity.runOnUiThread(Runnable)
  2. View.post(Runnable)
  3. View.postDelayed(Runnable, long)
  4. Handler

以上任何一种方式都能修正我们的代码:

public void onClick(View v) {  new Thread(new Runnable() {    public void run() {      final Bitmap b = loadImageFromNetwork();      mImageView.post(new Runnable() {        public void run() {          mImageView.setImageBitmap(b);        }      });    }  }).start();}

当然我们还有更简单的方法,使用AsyncTask

不幸的是,这些类和方法导致我们的代码变得复杂和可读性差。当你实现复杂的操作来频繁的更新界面,使用这种方式变得更加糟糕。为了解决这个问题,Android1.5提供了一个公共类叫做AsyncTask,它简化了任务线程和主线程之间的通信。 在Android1.0和1.1也可使用AsyncTask只不过它的名字为UserTask。 AsyncTask的目的就是帮助你管理线程。我们之前的例子很容易被改写如下形式:
public void onClick(View v) {  new DownloadImageTask().execute("http://example.com/image.png");}private class DownloadImageTask extends AsyncTask<string, integer, Bitmap> {     protected Bitmap doInBackground(String... urls) {         return loadImageFromNetwork(urls[0]);     }     protected void onPostExecute(Bitmap result) {         mImageView.setImageBitmap(result);     } }
AsyncTask通过它的子类才能使用。要记住,一个AsyncTask实例必须在主线程创建并且只能被执行一次。完全理解和使用这个类,你可以阅读AsyncTask文档。这里快速的说一下AsyncTask是怎么工作的: 1>可以通过泛型指定它的类型:参数,进度值,任务的结果值。 2>doInBackGround()方法自动在工作线程中只想能够。 3>onPreExecute(),onPostExecute(),onProgressUpdate()方法都在UI线程中执行。 4>doInBackground()方法返回的值被当作参数传递给onPostExecute()方法。 5>你能够在doInBackground()方法里任何时候调用publishProgress()方法在UI线程中去执行onProgressUpdate()方法。 下面写一个重载方法比较多得类:
 1 package vic.wong.main; 2 import android.os.AsyncTask; 3 import android.widget.ProgressBar; 4 import android.widget.TextView; 5  6 /** 7  * 生成该类的对象,并调用execute方法之后 8  * 首先执行的是onProExecute方法 9  * 其次执行doInBackgroup方法10  *11  */12 public class ProgressBarAsyncTask extends AsyncTask<Integer, Integer, String> {13     private TextView textView;14     private ProgressBar progressBar;15     public ProgressBarAsyncTask(TextView textView, ProgressBar progressBar) {16         super();17         this.textView = textView;18         this.progressBar = progressBar;19     }20     /**21      * 这里的Integer参数对应AsyncTask中的第一个参数 22      * 这里的String返回值对应AsyncTask的第三个参数23      * 该方法并不运行在UI线程当中,主要用于异步操作,所有在该方法中不能对UI当中的空间进行设置和修改24      * 但是可以调用publishProgress方法触发onProgressUpdate对UI进行操作25      */26     @Override27     protected String doInBackground(Integer... params) {28         NetOperator netOperator = new NetOperator();29         int i = 0;30         for (i = 10; i <= 100; i+=10) {31             netOperator.operator();32             publishProgress(i);33         }34         return i + params[0].intValue() + "";35     }36 37     /**38      * 这里的String参数对应AsyncTask中的第三个参数(也就是接收doInBackground的返回值)39      * 在doInBackground方法执行结束之后在运行,并且运行在UI线程当中 可以对UI空间进行设置40      */41     @Override42     protected void onPostExecute(String result) {43         textView.setText("异步操作执行结束" + result);44     }45     //该方法运行在UI线程当中,并且运行在UI线程当中 可以对UI空间进行设置46     @Override47     protected void onPreExecute() {48         textView.setText("开始执行异步线程");49     }50     /**51      * 这里的Intege参数对应AsyncTask中的第二个参数52      * 在doInBackground方法当中,,每次调用publishProgress方法都会触发onProgressUpdate执行53      * onProgressUpdate是在UI线程中执行,所有可以对UI空间进行操作54      */55     @Override56     protected void onProgressUpdate(Integer... values) {57         int vlaue = values[0];58         progressBar.setProgress(vlaue);59     }60 }

更多相关文章

  1. activity中onSaveInstanceState方法调用时机详解
  2. Android 利用getIdentifier()方法获取资源ID
  3. Android cursor query方法详解
  4. [置顶] Android系统安全之旅 第1章 编译Android程序的方法
  5. Android使背景灯(Brightness)高亮的方法
  6. android spinner自动弹出列表,设置title,TtextView不换行自动截取

随机推荐

  1. Nokia 为何只做 Windows Phone :我怕 Andr
  2. 详解Android首选项框架的使用实例
  3. 开发者应如何看待iOS平台和Android平台
  4. kxte9应用局限
  5. cocos2d-x 2.0.1版本的使用 在android 上
  6. 在PC虚拟机中安装apk软件
  7. android用户输入系统详细说明
  8. 移动流量差距继续拉大:iOS份额超60%,Androi
  9. android安全问题(四) 抢先开机启动
  10. 跟Google学习Android开发-起始篇-保存数