首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 移动开发 > Android >

Android线程模型跟AsyncTask

2012-11-11 
Android线程模型和AsyncTaskandroid 的线程模型:当一个 android 的应用运行后,就会有一个 UI 的 main 线程

Android线程模型和AsyncTask
android 的线程模型:当一个 android 的应用运行后,就会有一个 UI 的 main 线程启动 , 这是一个非常重要的线程,它负责把事件分派到相应的控件,其中就包括屏幕绘图事件,它同样是用户与 android 控件 交互的线程。比如,当你在屏幕上的 EditText 上输入文字, UI 线程会把这个事件分发给刚输入文字的 EditText ,紧接会向事件队列发送一个更新 ( invalidate )请求。 UI 线程会把这个请求移出事件队列并通知 EditText 在屏幕上重新绘制自身。

这种单线线程模型就会使得 android 的应用程序性能低下, 如果在这个单线程里执行一些耗时的操作, 比如访问数据库, 或是从网络端下载图片, 就会会阻塞整个用户界面。 比如如下操作:

1
Bitmap b =  loadImageFromNetwork();

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

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

1
new Thread(new Runnable() {
2
     public void run() {                       
3
          Bitmap b = loadImageFromNetwork();  
4
          mImageView.setImageBitmap( b );  
5
     }
6
}).start();
但这样会发生一些很难察觉的错误, 因为我们知道 UI 线程不是线程安全的。当然有很多种方法来处理这个问题:

android 提供了几种在其他线程中访问 UI 线程的方法。

? Activity.runOnUiThread( Runnable )
? View.post( Runnable )
? View.postDelayed( Runnable, long )
? Hanlder

1
new Thread( new Runnable() {  
2
            public void run() {  
3
                     final Bitmap b = loadImageFromNetwork();  
4
                     mImageView.post( new Runnable() {  
5
                     mImageView.setImageBitmap( b );  
6
});  
7
          }  
8
}).start();
这种方法比较繁琐,同时当你需要实现一些很复杂的操作并需要频繁地更新UI 时这会变得更糟糕。为了解决这个问题,android 提供了一个工具类:AsyncTask ,它使创建需要与用户界面交互的长时间运行的任务变得更简单。

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

01
ublic class CanvasImageTask extends AsyncTask<ImageView, Void, Bitmap>{
02
        private ImageView gView ;
03
        
04
    protected Bitmap doInBackground(ImageView... views) {
05
                Bitmap bmp = null ;
06
                ImageView view = views[0];
07
            // 根据iconUrl获取图片并渲染,iconUrl的url放在了view的tag中。
08
            if (view.getTag() != null) {
09
                    try {
10
                       URL url = new URL(view.getTag().toString());
11
                       HttpURLConnection conn = (HttpURLConnection)url.openConnection();
12
                       conn.setDoInput(true);
13
                       conn.connect();
14
                       InputStream stream = conn.getInputStream();
15
                       bmp = BitmapFactory.decodeStream(stream);
16
                       stream.close();
17
                    } catch (Exception e) {
18
                                Log.v("img", e.getMessage());
19
                            return null;
20
                    }
21
            }
22
            this.gView = view;
23
            return bmp;
24
    }
25
    protected void onPostExecute(Bitmap bm) {
26
            if (bm != null) {
27
                    this.gView.setImageBitmap(bm);
28
                    this.gView = null ;
29
            }
30
    }
31
    
32
}
33
在Activity中直接调用
34
if(!img.isDrawingCacheEnabled() || !holder.image.getTag().equals(imgpath)){
35
                img.setImageResource(R.drawable.icon_app);
36
                img.setTag(imgpath);
37
                try{
38
                    new CanvasImageTask().execute(img);
39
                    img.setDrawingCacheEnabled(true);
40
                }catch (Exception e) {
41
                    Log.e("error", "RejectedExecutionException in content_img: " +  imgpath);
这样图片加载使用异步线程便不会进行堵塞发生错误,我们还可以使用 callback 在图片加载完后进行回调
01
public class CanvasImageTaskCall extends AsyncTask<ImageView, Void, Bitmap> implements Callback{
02
    private ImageView gView ;
03
    
04
    protected Bitmap doInBackground(ImageView... views) {
05
            Bitmap bmp = null ;
06
            ImageView view = views[0];
07
            // 根据iconUrl获取图片并渲染,iconUrl的url放在了view的tag中。
08
            if (view.getTag() != null) {
09
                    try {
10
                       URL url = new URL(view.getTag().toString());
11
                       HttpURLConnection conn = (HttpURLConnection)url.openConnection();
12
                       conn.setDoInput(true);
13
                       conn.connect();
14
                       InputStream stream = conn.getInputStream();
15
                       bmp = BitmapFactory.decodeStream(stream);
16
                       stream.close();
17
                    } catch (Exception e) {
18
                            e.printStackTrace();
19
                            Log.v("img", e.getMessage());
20
                            Message msg = new Message();
21
                            msg.what = 0;
22
                            handleMessage(msg);
23
                            return null;
24
                    }
25
            }
26
            this.gView = view;
27
            return bmp;
28
    }
29
    protected void onPostExecute(Bitmap bm) {
30
            if (bm != null) {
31
                this.gView.setImageBitmap(bm);
32
                this.gView.setTag(bm);
33
                this.gView = null ;
34
                Message msg = new Message();
35
                msg.what = 1;
36
                handleMessage(msg);
37
            }
38
    }
39
    public boolean handleMessage(Message msg) {
40
        // TODO Auto-generated method stub
41
        return false;
42
    }
43
    
44
}
在 Activity 中直接调用
view sourceprint?
01
new CanvasImageTaskCall(){
02
                        @Override
03
                        public boolean handleMessage(Message msg) {
04
                                switch (msg.what) {
05
                                case 0:
06
                                        Log.i("test", "图片加载失败");
07
                                        break;
08
                                case 1:
09
                                        Log.i("test", "图片加载成功");
10
                                        break;
11
                                default:
12
                                        break;
13
                                }
14
                                saveButton.setTextColor(Color.WHITE);
15
                                saveButton.setClickable(true);
16
                                bitmap = (Bitmap) imageView.getTag();
17
                                return super.handleMessage(msg);
18
                        }
19
                }.execute(img);
来源:http://www.verydemo.com/demo_c230_i480.html

热点排行