在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. 文字位于RadioButton后,如何调整间距?
  2. android webview 加载进度和自定义404错误页面
  3. Android(安卓)应用性能调试
  4. activity中onSaveInstanceState方法调用时机详解
  5. Android(安卓)利用getIdentifier()方法获取资源ID
  6. Android(安卓)MapView 申请apiKey
  7. Activity启动过程分析
  8. 浅谈Java中Collections.sort对List排序的两种方法
  9. Python list sort方法的具体使用

随机推荐

  1. 避免在Android上冷启动
  2. 探索Android中的Parcel
  3. android 开发环境安装和测试中常出现的问
  4. Android读取JSON格式数据
  5. Android(安卓)Animation学习
  6. androidUI控件
  7. Android.PublishApplication
  8. Android(安卓)存储目录
  9. Android(安卓)ViewPager实现Tabhost选项
  10. Android(安卓)应用程序获得版本号