参考教程:iMooc关于Handler,http://www.imooc.com/learn/267
参考资料:Google提供Android文档Communicating with the UI Thread
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的机制管理线程操作更加条理。