概念:
MessageQueue:消息队列,存放消息的地方,按照FIFO(先进先出)规则执行,每一个线程只可以拥有一个MessageQueue,在创建looper对象会创建一个MessageQueue对象
Message:消息对象,MessageQueue中存放的对象,一个MessageQueue中可以包含多个Message对象,可以通过Message.obtain()或Message.obtainMessage()获取Message对象,但是并不一定是直接创建一个新的实例,而是先从消息池中看有没有可用的Message实例,存在则直接取出返回这个实例,如果消息池中没有可用的Message实例,则才用给定的参数创建一个Message对象,调用removeMessage()将message对象从MessageQueue中删除,同时放入到消息池中
Looper:操作MessageQueue.一个Looper对应一个MessageQueue.通过调用Loop.myLooper()可以获得当前线程的Looper对象.Looper从MessageQueue中取出Message后,交给Handler的handleMessage()进行处理.处理完后,调用Message.recycle()将其放入消息池中
Handler:消息的处理者,handler负责将需要传递的信息封转成Message对象,然后调用sendMessage()方法将消息放入到MessageQueue中,当MessageQueue循环到该Message,
调用相应的Handler对象的HandleMessage()方法对其进行处理,Handler都可以共享同一个Looper和MessageQueue
handler类允许你发送消息和处理线程消息队列中的消息及runnable对象。handler实例都是与一个线程和该线程的消息队列一起使用,一旦创建了一个新的handler实例,系统就把该实例与一个线程和该线程的消息队列捆绑起来,这将可以发送消息和runnable对象给该消息队列,并在消息队列出口处处理它们。
handler类有两种主要用途:1。按照时间计划,在未来某时刻,对处理一个消息或执行某个runnable实例。2。把一个对另外线程对象的操作请求放入消息队列中,从而避免线程间冲突。
时间类消息通过如下方法使用: post(Runnable), postAtTime(Runnable, long), postDelayed(Runnable, long), sendEmptyMessage(int), sendMessage(Message), sendMessageAtTime(Message, long), and sendMessageDelayed(Message, long)
methods. post之类函数可以传输一个runnable对象给消息队列,并在到达消息队列后被调用。sendmessage之类函数可以传送一个包含数据的message对象,该message对象可以被Handler类的handleMessage(Message) 方法所处理。
post之类函数和sendmessage之类的函数都可以指定消息的执行时机,是立即执行、稍后一段时间执行,还是在某个确定时刻执行。这可以用来实现超时、消息或其他时间相关的操作。
当一个进程启动时,主线程独立执行一个消息队列,该队列管理着应用顶层的对象(如:activities、broadcast receivers等等)和所有创建的窗口。你可以创建自己的一个线程,并通过handler来与主线程进行通信。这可以通过在新的线程中调用主线程的handler的post和sendmessage操作来实现。
1、布局文件main.xml
- <ProgressBar
- android:id="@+id/myProBar"
- style="?android:attr/progressBarStyleHorizontal"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:visibility="gone"/> //将ProgressBar设置为不可见
- <Button
- android:id="@+id/btnStart"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="@string/btnStart"/>
2、Activity文件中的代码如下
- / /声明控件变量
- ProgressBar proBar;
- Button btnStart;
- int i=0;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- //根据控件的ID得到控件的对象
- roBar=(ProgressBar)this.findViewById(R.id.myProBar);
- btnStart=(Button)this.findViewById(R.id.btnStart);
- //为btnStart按钮绑定监听器
- btnStart.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View arg0) {
- proBar.setVisibility(View.VISIBLE);
- updateBarHandler.post(updateThread);
- }
- //使用匿名内部类来复写Handle当中的handlerMessage()方法
- Handler updateBarHandler=new Handler(){
- @Override
- public void handlerMessage(Message msg) {
- //将进度条设置为可见
- proBar.setProgress(msg.arg1);
- //调用Handler的post()方法,将要执行的线程对象添加到队列当中
- updateBarHandler.post(updateThread);
- }
- };
- //线程类,该类使用匿名内部类的方式进行声明
- Runnable updateThread=new Runnable()
- {
- //将要执行的操作写在线程对象的run()方法当中
- @Override
- public void run() {
- i+=10;
- //得到一个消息,Message类是由android操作系统提供
- Message msg=updateBarHandler.obtainMessage();
- //可以用arg1和arg2这两个成员变量传递消息
- msg.arg1=i;
- try{
- //睡眠1秒
- Thread.sleep(1000);
- }
- catch(InterruptedException e) {
- e.printStackTrace();
- }
- //将msg对象加入到消息队列当中(加入到消息队列中就立刻返回,不管消息是否被处理(异步),会调用handleMessage()方法)
- updateBarHandler.sendMessage(msg);
- if(i==100)
- {
- //将线程对象从队列中移除
- updateBarHandler.removeCallbacks(updateThread);
- }
- }
- };
- });
- }
3、运行结果
1.Handler与线程
实际上Handler与Activity处于同一线程当中
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Handler handler=new Handler();
- handler.post(r);
- setContentView(R.layout.main);
- System.out.println("activity--->"+Thread.currentThread().getId());
- System.out.println("activity--->"+Thread.currentThread().getName());
- }
- Runnable r=new Runnable(){
- @Override
- public void run() {
- System.out.println("handler--->"+Thread.currentThread().getId());
- System.out.println("handlerName--->"+Thread.currentThread().getName());
- try {
- Thread.sleep(10000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
handersetCotentView()之前,所有要等待10秒,Activity中的内容才显示处理,并且输出的id和name相同,则说明Handler没有启动新线程,
2.在新线程当中处理消息方法,(需要使用Looper对象,改对象提供了循环的从队列中取消息的这种功能),并使用Bundle
- package wei.cao.handler;
- import android.app.Activity;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.HandlerThread;
- import android.os.Looper;
- import android.os.Message;
- public class Handler_03 extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- System.out.println("Activity--->"+Thread.currentThread().getId());
- //生成一个HandlerThread对象,实现了使用looper来处理消息的功能,这个类由Android应用程序框架提供
- HandlerThread handlerThread=new HandlerThread("handler_thread");
- //在使用HandlerThread的getLooper()方法之前,必须先调用该类的start()方法,否在调用getLooper()方法返回null
- handlerThread.start();
- MyHandler myHandler=new MyHandler(handlerThread.getLooper());
- //将Msg发送到目标对象,所谓的目标对象,就是生成msg对象的hand对象
- Message msg=myHandler.obtainMessage();
- //使用Bundler对象来传递数据
- Bundle b=new Bundle();
- b.putString("name", "wei_cao");
- b.putInt("age", 10);
- msg.obj="abc";
- msg.setData(b);
- msg.sendToTarget();
- }
- class MyHandler extends Handler
- {
- public MyHandler(Looper looper)
- {
- super(looper);
- }
- @Override
- public void handleMessage(Message msg) {
- String str=(String)msg.obj;
- //从消息中取出Bundle对象
- Bundle b=msg.getData();
- String name=b.getString("name");
- int age=b.getInt("age");
- System.out.println("name is "+name+"age is "+age+"str is "+str);
- System.out.println("Handler--->"+Thread.currentThread().getId());
- System.out.println("handleMessage");
- }
- }
- }