Handle和Looper

本文深入探讨Android应用中Handler的使用方式,包括其核心组件Looper、MessageQueue、Message及其重要属性,以及如何在不同线程中正确地使用Handler实现异步更新UI的功能。特别强调了在主线程和非主线程中使用Handler的区别,并通过实例展示了如何利用Handler实现异步更新UI的例子。

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

class LooperThread extends Thread {
      public Handler mHandler;
        
       public void run() {
            Looper.prepare();
          
			mHandler = new Handler() {
               public void handleMessage(Message msg) {
                   // process incoming messages here
               }
            };
           
            Looper.loop();
  
			new Thread(new Runable{
			
				run(){
					
					mHandler.send(msg);
				
				}
			
			}).start();
		}
	}

1、Handler有以下重要属性

 final MessageQueue mQueue;

 final Looper mLooper;

这两个属性都和Looper关联,直接来自于Looper 如以下

  /**
     * Default constructor associates this handler with the queue for the
     * current thread.
     *
     * If there isn't one, this handler won't be able to receive messages.
     */
    public Handler() {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }

        mLooper = Looper.myLooper();//获取当前线程关联的Looper, 常由Looper.prepare()进行关联
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = null;
    }
所以我们向Handler中发送Msg或Post Runable 时 ,实质上是向关联的Looper.mQueue中添加Message对象。

而Message中主要有以下重要属性

    /*package*/ Bundle data;    //发送时绑定的数据
    
    /*package*/ Handler target;     //和msg绑定的Handler
    
    /*package*/ Runnable callback;   //postRunable

2、对于Looper

有一个很重要的属性

final MessageQueue mQueue;//消息队列

使用:1、执行Looper.prepare();

给当前线程绑定一个新Looper对象,包括新的序列

  /** Initialize the current thread as a looper.
      * This gives you a chance to create handlers that then reference
      * this looper, before actually starting the loop. Be sure to call
      * {@link #loop()} after calling this method, and end it by calling
      * {@link #quit()}.
      */
    public static final void prepare() {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper());
    } 
    
    private Looper() {
        mQueue = new MessageQueue();
        mRun = true;
        mThread = Thread.currentThread();
    }
2、执行Looper.loop()开始循环取队列并派发消息处理


所以我们在新线程中使用Handler时就必须调用Looper.prepare()和Looper.loop()

class LooperThread extends Thread {
      public Handler mHandler;
        
       public void run() {
            Looper.prepare();
          
	    mHandler = new Handler() {
               public void handleMessage(Message msg) {
                   // process incoming messages here
               }
            };
           
            Looper.loop();
  
			new Thread(new Runable{
			
				run(){
					
					mHandler.send(msg);
				
				}
			
			}).start();
		}
	}

然而为什么在主线程中而不必调用这两个方法呢?因为主线程一启动就已经执行这两个方法,所以我们常在主线程中直接就可以使用handle如下:

mHandler = new Handler() {
               public void handleMessage(Message msg) {
                   // process incoming messages here
               }
            };


使用Handler实现异步更新UI例子synHandlerUpdateUI.zip


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值