• android 的线程模型和AsyncTask


            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);


  • 相关阅读:
    处在什么都想学,却又不知道怎么学的处境
    启动MongoDB shell客户端会什么会一闪而过
    Socket.io发送消息含义
    轮询、长轮询与Web Socket的前端实现
    org.apache.commons.lang3.StringUtils类中isBlank和isEmpty方法的区别
    JS学习笔记10_Ajax
    JS学习笔记9_JSON
    JS学习笔记8_错误处理
    JS学习笔记7_表单脚本
    JS学习笔记6_事件
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3212337.html
Copyright © 2020-2023  润新知