Android中处理异步的第一选择和最佳选择,就是AsynTask这个类,因为他使用起来最方便,安全。

再介绍另外一个在开发中用的很多的异步大杀器,用于处理异步消息的,处理一些耗时操作,处理后台运行的程序并且要更新ui的情况,他就是Handler。
Handler主要接受子线程发送的数据, 并用此数据配合主线程更新UI.。

当应用程序操作应用程序的时候,出现一些比较耗时的操作,譬如 从网上下载数据,读取本地较大的文件,这时不能把这些操作 放在主线程,因为这样会阻塞主线程,而且如果5秒钟还没有完成的话,就会出席那ANR(应用程序无响应)的错误。所以我们需要把耗时操作放在子线程进行操作。这样是可以处理了主线程被阻塞的麻烦,但是如果如果我们想更新UI,而在子线程中操作是不安全的,无法预料后面发生的事情(Andoid UI toolkit不是线程安全的,所以注意在android使用线程的两个点:a > 不要阻塞UI线程; b > 不要再主线程外的线程操控UI线程(即更新UI)),这个时候就体现出了Handler的价值了。

Handler是在主线程(UI线程)中运行,他与子线程通过Message来传递数据(通过SendMessage()发送个主线程),而主线程中有个消息队列MessageQueue来存储,HandleMessage()一个一个的从队列中取出消息,并相应的进行处理,更新ui。

当创建了Handler对象,他就会与他所在的线程以及消息队列进行绑定,这样发送Message或Runable,就可以发送给消息队列做相应的处理了。一个线程可以有多个handler,各自处理各自的相对应的消息;但是一个线程只有一个looper,当然也就只有一个消息循环。这里还要注意一个问题,在一个普通的子线程中创建handler,因为没有调用Looper.prepare(),没有Looper实例,所以会出现异常,同时这也说明一个普通的子线程没有Looper实例,没有消息循环。所以在一个普通的子线程中发送消息是不行的,当然我们可以自己创建Looper实例(a.子线程中创建一个消息队列(就是Looper对象,通过prepare(),loop()); b.得到主线程中得消息队列,操控主线程的消息队列Looper.getMainLooper())。但是我们一般这么做,而是使用另外一个类,叫做HandlerThread,这个自身有Looper实例。


看下下面的代码片段:

public class HandlerDemo extends Activity {private final static int MESSAGE_ID = 5;private TestHandler1 mTestHandler1;/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);mTestHandler1 = new TestHandler1();  // 创建handler实例Button btn = (Button) findViewById(R.id.clcik);btn.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View v) {// TODO Auto-generated method stubnew Thread(new Runnable(){                // 从子线程发送消息给ui线程        @Overridepublic void run() {// TODO Auto-generated method stub// 发送消息// 直接从handler获取message对象,当然也可以new一个,但是推荐前一个Message msg = mTestHandler1.obtainMessage();              Bundle b = new Bundle();b.putString("color", "red");// 给handler发送的数据,放入message中msg.setData(b);msg.what = MESSAGE_ID;mTestHandler1.sendMessage(msg);                        }}).start();}});}private class TestHandler1 extends Handler    // 实现handler          {@Overridepublic void handleMessage(Message msg) {// TODO Auto-generated method stubsuper.handleMessage(msg);if (msg.what == MESSAGE_ID) {                  Bundle b = msg.getData();String colorStr = b.getString("color");Log.d("HandlerDemo", "TestHandler1---------"+colorStr);}}}}

继承于handler的子类TestHandler1,并在主线程中分别创建对象;

创建一个子线程,在子线程用主线程中定义的mTestHandler1对象,发送消息给主线程,并在主线程中的HandleMessage中做相应的处理;

Message msg = mTestHandler1.obtainMessage();               Bundle b = new Bundle();b.putString("color", "red");// 给handler发送的数据,放入message中msg.setData(b);msg.what = MESSAGE_ID;mTestHandler1.sendMessage(msg);   
这一部分会在Message中做相应的介绍,这里就不解释了。

总结:

1.handler的作用(为什么使用handler):

1)按计划发送消息或执行某个Runnanble(使用POST方法),类似定时器
2)从其他线程中发送来的消息放入消息队列中,避免线程冲突(常见于更新UI线程);

2.当handler在一个线程中创建,就会与他所在的线程和消息队列进行绑定;

3.一个线程对应一个Looper(消息循环),一个MessageQueue(消息队列)

4.一个线程中可以对应多个handler,但是共用一个Looper和MessageQueue;

5.handler可以从任何线程发送消息(前提必须有looper实例);

更多相关文章

  1. SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
  2. android集成Umeng推送获取不到device_token也收不到消息,但是在Um
  3. Android(安卓)IPC【Inter-Process Communication】机制二【Andro
  4. Android/Swing中并发分析
  5. android不同线程间通讯~
  6. Android(安卓)极光IM简单的聊天界面全手动实现
  7. Android实现聊天机器人之火影忍者
  8. android异常 android.os.NetworkOnMainThreadException
  9. 获取mic音量大小

随机推荐

  1. Android(安卓)RelativeLayout用到的一些
  2. Android面试题集(2019-04-04总结)
  3. android Progress style (长进度条)
  4. Android(安卓)EditText
  5. Android(安卓)分类法:六个类型,八种用户
  6. Virtual Box 虚拟机安装Android
  7. Android进程,任务,服务的信息
  8. 浅析Android线程模型一 --- 转
  9. Android(安卓)背景色平铺。
  10. Android(安卓)ART运行时与Dalvik虚拟机