参考教程:iMooc关于Handler,http://www.imooc.com/learn/267

参考资料:Google提供Android文档Communicating with the UI Thread

Handler的作用:

  Android开发中不允许UI主线程之外的线程更新,那么在主线程下建立Handler对象用于接收其他线程传来的数据(由Message携带)更新UI是Android提供的方法之一,另一个是我们熟知的更加轻量的AsyncTask类,这里不做展开,详细的Handler+Thread与AsyncTask的区别见AsyncTask和Handler的优缺点比较。将耗时的操作用其他Thread执行,执行完毕后传送给Handler对象一个Message,然后由Handler将传来的数据交给UI主线程。

  Handler要解决的根本问题是Android线程并发,如果没有相应的机制约束各线程的协作并发,很容易导致开发上和运行上的混乱。Android处理多线程的方式也不是传统上的加锁机制(性能因素吧),而是MessageQueue,即消息队列,开发者可以直接控制消息队列的显示顺序和方式,这样就不会产生数据的同步混乱的问题了。

  写一个小Demo,帮助理解Handler的使用。用新建Thread处理下载图片和显示图片两个操作。

  在MainActivity的onCreate方法中添加一个新的线程:

        //初始化View
        imageView = (ImageView) findViewById(R.id.imageView);
        //添加Thread用于下载图片和更新UI
        new Thread(new MyRunnable()).start();     

  

  MyRunnable类

public class MyRunnable implements Runnable {

    Activity mActivity;

    private Message msg;
    private Bitmap imageBitmap;
    private static final String urlData = "http://sfault-avatar.b0.upaiyun.com/166/281/166281916-1140000000145114_huge128";
    @Override
    public void run() {
        msg  = new Message();
        imageBitmap = getHttpImage(urlData);
        msg.obj = imageBitmap;
        
        //将imageBitmap用msg传给MainActivity中的handler
        MainActivity.handler.sendMessage(msg);

    }

    //用网址 urlData 读取图片的Bitmap
    private Bitmap getHttpImage(String urlData) {
        Bitmap bitmap = null;
        try {
            URL url = new URL(urlData);
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
            httpURLConnection.setConnectTimeout(5*1000);
            httpURLConnection.setDoInput(true);
            httpURLConnection.connect();

            InputStream inputStream = httpURLConnection.getInputStream();
            bitmap = BitmapFactory.decodeStream(inputStream);

            inputStream.close();
            httpURLConnection.disconnect();

        } catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return bitmap;
    }
}

  回到MainActivity中,初始化handler,并重写其handleMessage方法,代码如下:

public static Handler handler = new Handler(Looper.getMainLooper()){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            //从msg中获取图片的bitmap
            Bitmap bitmap = (Bitmap) msg.obj;
            //更新UI
            imageView.setImageBitmap(bitmap);
        }
    };

总结,用Handler+Thread的方式执行单一线程确实比较繁琐,用AsyncTask会更简洁高效。但是在比较复杂的多线程应用场景下,用Handler建立MessageQueue的机制管理线程操作更加条理。

 

Posted on 2015-01-23 22:09  BryceMa  阅读(1984)  评论(0编辑  收藏  举报