Handler的使用

本文深入解析了Android消息机制,包括MessageQueue、Message、Looper和Handler的工作原理及其应用场景。通过实例展示了如何利用Handler更新UI,以及如何在不同线程间通过Looper进行消息传递。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概念:

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");
	}
	 
	 
 }
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值