移动云

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 3963|回复: 0

Android线程模型和AsyncTask

[复制链接]
发表于 2012-2-23 17:33:13 | 显示全部楼层 |阅读模式
本帖最后由 T268 于 2012-2-23 17:34 编辑

android 的线程模型:当一个 android 的应用运行后, 就会有一个 UI 的 main 线程启动 , 这是一个非常重要的线程,它负责把事件分派到相应的控件,其中就包括屏幕绘图事件,它同样是用户与 android 控件 交互的线程。比如,当你在屏幕上的 EditText 上输入文字, UI 线程会把这个事件分发给刚输入文字的EditText ,紧接会向事件队列发送一个更新 ( invalidate )请求。 UI 线程会把这个请求移出事件队列并通知 EditText 在屏幕上重新绘制自身。
       这种单线线程模型就会使得 android 的应用程序性能低下, 如果在这个单线程里执行一些耗时的操作, 比如访问数据库, 或是从网络端下载图片, 就会会阻塞整个用户界面。 比如如下操作:

         Bitmap b =  loadImageFromNetwork();

这个操作非常耗时, 在这种情况下你会发现 , 界面僵死在那里并且 android 在系统 5 秒中后没有反应,会显示一个关闭或等待的错误。

         也许我们可以使用一个新的 Thread 来解决它


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




但这样会发生一些很难察觉的错误, 因为我们知道 UI 线程不是线程安全的。当然有很多种方法来处理这个问题:
android 提供了几种在其他线程中访问 UI 线程的方法。
• Activity.runOnUiThread( Runnable )
• View.post( Runnable )
• View.postDelayed( Runnable, long )
• Hanlder


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



这种方法比较繁琐,同时当你需要实现一些很复杂的操作并需要频繁地更新UI 时这会变得更糟糕。为了解决这个问题,android 提供了一个工具类:AsyncTask ,它使创建需要与用户界面交互的长时间运行的任务变得更简单。

       就拿加载网络图片举个例子:


  • ublic class CanvasImageTask extends AsyncTask<ImageView, Void, Bitmap>{  
  •         private ImageView gView ;  
  •          
  •     protected Bitmap doInBackground(ImageView... views) {  
  •                 Bitmap bmp = null ;  
  •                 ImageView view = views[0];  
  •             // 根据iconUrl获取图片并渲染,iconUrl的url放在了view的tag中。  
  •             if (view.getTag() != null) {  
  •                     try {  
  •                        URL url = new URL(view.getTag().toString());  
  •                        HttpURLConnection conn = (HttpURLConnection)url.openConnection();  
  •                        conn.setDoInput(true);  
  •                        conn.connect();  
  •                        InputStream stream = conn.getInputStream();  
  •                        bmp = BitmapFactory.decodeStream(stream);  
  •                        stream.close();  
  •                     } catch (Exception e) {  
  •                                 Log.v("img", e.getMessage());  
  •                             return null;  
  •                     }  
  •             }  
  •             this.gView = view;  
  •             return bmp;  
  •     }  
  •     protected void onPostExecute(Bitmap bm) {  
  •             if (bm != null) {  
  •                     this.gView.setImageBitmap(bm);  
  •                     this.gView = null ;  
  •             }  
  •     }  
  •       
  • }  
  • 在Activity中直接调用  
  • if(!img.isDrawingCacheEnabled() || !holder.image.getTag().equals(imgpath)){  
  •                 img.setImageResource(R.drawable.icon_app);  
  •                 img.setTag(imgpath);  
  •                 try{  
  •                     new CanvasImageTask().execute(img);  
  •                     img.setDrawingCacheEnabled(true);  
  •                 }catch (Exception e) {  
  •                     Log.e("error", "RejectedExecutionException in content_img: " +  imgpath);  



这样图片加载使用异步线程便不会进行堵塞发生错误,我们还可以使用 callback 在图片加载完后进行回调



  • public class CanvasImageTaskCall extends AsyncTask<ImageView, Void, Bitmap> implements Callback{  
  •     private ImageView gView ;  
  •       
  •     protected Bitmap doInBackground(ImageView... views) {  
  •             Bitmap bmp = null ;  
  •             ImageView view = views[0];  
  •             // 根据iconUrl获取图片并渲染,iconUrl的url放在了view的tag中。  
  •             if (view.getTag() != null) {  
  •                     try {  
  •                        URL url = new URL(view.getTag().toString());  
  •                        HttpURLConnection conn = (HttpURLConnection)url.openConnection();  
  •                        conn.setDoInput(true);  
  •                        conn.connect();  
  •                        InputStream stream = conn.getInputStream();  
  •                        bmp = BitmapFactory.decodeStream(stream);  
  •                        stream.close();  
  •                     } catch (Exception e) {  
  •                             e.printStackTrace();  
  •                             Log.v("img", e.getMessage());  
  •                             Message msg = new Message();  
  •                             msg.what = 0;  
  •                             handleMessage(msg);  
  •                             return null;  
  •                     }  
  •             }  
  •             this.gView = view;  
  •             return bmp;  
  •     }  
  •     protected void onPostExecute(Bitmap bm) {  
  •             if (bm != null) {  
  •                 this.gView.setImageBitmap(bm);  
  •                 this.gView.setTag(bm);  
  •                 this.gView = null ;  
  •                 Message msg = new Message();  
  •                 msg.what = 1;  
  •                 handleMessage(msg);  
  •             }  
  •     }  
  •     public boolean handleMessage(Message msg) {  
  •         // TODO Auto-generated method stub  
  •         return false;  
  •     }  
  •       
  • }  



在 Activity 中直接调用


  • new CanvasImageTaskCall(){  
  •                         @Override  
  •                         public boolean handleMessage(Message msg) {  
  •                                 switch (msg.what) {  
  •                                 case 0:  
  •                                         Log.i("test", "图片加载失败");  
  •                                         break;  
  •                                 case 1:  
  •                                         Log.i("test", "图片加载成功");  
  •                                         break;  
  •                                 default:  
  •                                         break;  
  •                                 }  
  •                                 saveButton.setTextColor(Color.WHITE);  
  •                                 saveButton.setClickable(true);  
  •                                 bitmap = (Bitmap) imageView.getTag();  
  •                                 return super.handleMessage(msg);  
  •                         }  
  •                 }.execute(img);  

文章转自


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|管理员QQ:44994224|邮箱(t268studio@gmail.com)|Archiver|MCLOUDER

GMT+8, 2025-7-2 06:47 , Processed in 0.044164 second(s), 16 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表