Looper/Handler/MessageQueue/Message/AsyncResult/Registrant/RegistrantList

一、Looper, MessageQueue, Handler, Message之间的关系

Message:消息,其中包含了消息ID (what), 消息处理对象 (Handler target) 以及处理的数据等,由 MessageQueue 统一列队 (enqueueMessage), 最终由Handler处理。

Handler:处理者,负责Message的发送 (sendMessage) 及处理 (dispatchMessage->handleMessage). 使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。

MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。

Looper:消息泵,不断地从MessageQueue中抽取Message, 然后调用Message指定 (target) 的具体HandlerdispatchMessageMessage进行处理

一个MessageQueue需要一个Looper。即一个线程只能有一个Looper和一MessageQueue, 是可以有多个Handler.

Thread:线程,负责调度整个消息循环,即消息循环的执行场所。


、如何建立Handler的通信机制

  1. 初始Looper

首先两个线程要分别建立LooperMessageQueue. 

Note: 个线程中LooperMessageQueue能有一个Handler以有多个。

Looper.prepare();

    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

一个线程在调用Looper的静态方法prepare()时,这个线程会新建一个Looper对象,并放入到线程的局部变量中,而这个变量是不和其他线程共享的。看看Looper()这个构造函数,

    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

以看到在 Looper构造函数中,新建了一个final MessageQueue. 获得Looper绑定的线程


  1. 绑定handler到线程实例的Looper

mHandler= new Handler()看下具体的实现

   public Handler(Callback callback, boolean async) {
        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());
            }
        } //mem leak的提示

        mLooper = Looper.myLooper();  //获得当前的线程的Looper
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue; <span style="font-size: 14.6666669845581px; font-family: Calibri; widows: auto;">//获得当前的线程的 MessageQueue</span>
        mCallback = callback;
        mAsynchronous = async;
    }

绑定过程:通过Looper静态方法myLooper获得该线程的Looper,并赋值handlermLooper, 同时获得mQueue, mCallback.


  1. 自定义处理消息的方法

@override
handleMessage(Message msg) {
}

  1. 启动消息循环

Looper.loop();  //loop是一个静态方法

   public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;

        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }

            // This must be in a local variable, in case a UI event sets the logger
            Printer logging = me.mLogging;

            msg.target.dispatchMessage(msg);

            msg.recycle();
        }
    }
 

myLooper获得当前线程的looper, prepare函数中设置到sThreadLocal

public static Looper myLooper() {

        return sThreadLocal.get();

    }

queue = me.mQueue //获得当前线程的MessageQueue. new Looper()中初始化

  for (;;) {
            Message msg = queue.next(); // might block
            msg.target.dispatchMessage(msg);

            ...
            msg.recycle();
        }
    }

  接着在一个 for 死循环里,不断的遍历 MessageQueue 里的 message,  然后将该 message route 到创建该 message target(handler) dispatchMessage 里开始处理,而该 dispatchMessage 就是第 c 步覆写的 dispatchMessage()

到此一个Handler的事件处理就建立起来了。

 

Message的生成与发送

接下来看下Message是怎么建立的,有两种方法

  1. 用直接 new Message(), 然后手动填上what, arg1, arg2, target

   用Message里的静态obtain()方法,传入handler, what, arg1, arg2

  1. telephony中方法1用得比较少,用得最多的是用 HandlerobtainMessage(),

  事实上obtainMessage()最终也是调用的Message.obtain(),这样有个好处是直接用当前handler了。

: obtainMessage()

    public final Message obtainMessage(int what)
    {
        return Message.obtain(this, what); //this指当前的handler
    }

Message创建 好后,是怎么 送到 targetMessageQueue 的呢?

    public void sendToTarget() {
        target.sendMessage(this);
    }

T arget也就 入的handler

sendMessage->sendMessageDelayed->sendMessageAtTime
 public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
    MessageQueue queue = mQueue; //找到线程的MessageQueue
    if (queue == null) {
        RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
        Log.w("Looper", e.getMessage(), e);
        return false;
    }
    return enqueueMessage(queue, msg, uptimeMillis); //Message enqueue
}

最后 调用 MessageQueue enqueueMessage

 //下面这个DEMO是用来测试主线程和子线程互发消息的例子。

public class MainActivity extends Activity implements OnClickListener {

	Button mButton;
	LooperThread mThread;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mButton = (Button) findViewById(R.id.button);
		mButton.setOnClickListener(this);
		showLooper();
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.button:
			pressButton();
			break;

		default:
			break;
		}
	}

	private void pressButton() {
		//开启一个线程
		mThread = new LooperThread(); 
		mThread.start();
	}

	//线程
	class LooperThread extends Thread {
		public Handler mLooperThreadHandler;
		@Override
		public void run() {
			Looper.prepare(); //将LooperThread初始化为一个Looper
			mLooperThreadHandler = new LooperThreadHandler(Looper.myLooper());
			showLooper();
			Message msg = Message.obtain();
			msg.what = 100;
			mHandler.sendMessage(msg); //往主线程发送消息 
			Looper.loop();
		}
	}

	private class LooperThreadHandler extends Handler {
		public LooperThreadHandler(Looper looper) {
			super(looper);
		}

		@Override
		public void handleMessage(Message msg) {
			log("Looper Handler received "+msg.what);
			showLooper();
		}
	}

	private Handler mHandler = new Handler() {
		@Override
		public void dispatchMessage(Message msg) {
			log("Main:" + "received " + msg.what);
			showLooper();
			//往子线程里发送消息
			Message msg1 = mThread.mLooperThreadHandler.obtainMessage(1000);
			mThread.mLooperThreadHandler.sendMessage(msg1);
		}
	};

	private void showLooper() {
		log("In Looper:"+Looper.myLooper());
		log("Current thread:"+Thread.currentThread());
		log("-------------------------------------");
	}

	private void log(String str) {
		Log.d("bobby", str);
	}
}

以下是打印的log

D/bobby   ( 5492): In Looper:Looper (main, tid 1) {4243e4a8}

D/bobby   ( 5492): Current thread:Thread[main,5,main]
D/bobby   ( 5492): -------------------------------------
D/bobby   ( 5492): In Looper:Looper (Thread-2159, tid 2159) {425afe68}
D/bobby   ( 5492): Current thread:Thread[Thread-2159,5,main]
D/bobby   ( 5492): -------------------------------------
D/bobby   ( 5492): Main:received 100
D/bobby   ( 5492): In Looper:Looper (main, tid 1) {4243e4a8}
D/bobby   ( 5492): Current thread:Thread[main,5,main]
D/bobby   ( 5492): -------------------------------------
D/bobby   ( 5492): Looper Handler received 1000
D/bobby   ( 5492): In Looper:Looper (Thread-2159, tid 2159) {425afe68}
D/bobby   ( 5492): Current thread:Thread[Thread-2159,5,main]
D/bobby   ( 5492): -------------------------------------

四、AsyncResult

telephony中,Message处理中用得比较多还AsyncResult

RIL.java  processSolicited中对每个来的Request 

 
        if (error != 0) {  // Request有exception
            rr.onError(error, ret);
/*** 传入exception,该exception是从QCRIL里返回的。
        if (mResult != null) {
            AsyncResult.forMessage(mResult, ret, ex);
            mResult.sendToTarget();
        }
***/
        } else { //Request没有exception
 
            if (rr.mResult != null) {
                AsyncResult.forMessage(rr.mResult, ret, null); 
//rr.mResult是一个Message, 将返回的AsyncResult封装进入Message.obj, AsyncResult包
//含Request 的结果,以及一些异常结果
                rr.mResult.sendToTarget();
            }
        }
 
=========== AsyncResult.java
    /** Saves and sets m.obj */
    public static AsyncResult 
    forMessage(Message m, Object r, Throwable ex)
    {
        AsyncResult ret;
        ret = new AsyncResult (m.obj, r, ex);
        m.obj = ret; 
        return ret;
    }
    /** please note, this sets m.obj to be this */
    public 
    AsyncResult (Object uo, Object r, Throwable ex)
    {
        userObj = uo;
        result = r;
        exception = ex;
    }

Registrant, RegistrantList


Registrant之前,首先来看一段代码

 

 

个函数广泛的用在telephony卡状态变化,就需要通知注册函数的Handler.

么这种通知是如何实现的呢。Registrant.java, RegistrantList.java

 

protected RegistrantList mIccChangedRegistrants = new RegistrantList();
new 一个 RegistrantList 对象, 会在RegistrantList类里会自动new一个ArrayList,用来保存所有加入的单个Registrant
public
Registrant(Handler h, int what, Object obj)
{
    refH = new WeakReference(h);//定义一个弱引用
    this.what = what;   //不同的事件
    userObj = obj;
}
public synchronized void
add(Registrant r)
{
    removeCleared(); //将已经被回收了的Handler从Registrants里移出
    registrants.add(r);
}
new 一个 Registrant对象, 并将该对象加入到 registrants中。
 
r.notifyRegistrant() -> r. internalNotifyRegistrant()
internalNotifyRegistrant (Object result, Throwable exception)
{
    Handler h = getHandler(); //new Registrant对象时传入的Handler
 
    if (h == null) {
        clear();
    } else {
        Message msg = Message.obtain(); //生成一个Message对象
        msg.what = what;   // 
        msg.obj = new AsyncResult(userObj, result, exception);
                           //用AsyncResult的方法        
        h.sendMessage(msg); //将消息发送到MessageQueue里处理
    }
}

Registrant/RegistrantList通知机制都是based on Handler/Message/MessageQueue的。

参考

http://www.cnblogs.com/xirihanlin/archive/2011/04/11/2012746.html 

http://blog.csdn.net/oracleot/article/details/19163007  

http://blog.163.com/gobby_1110/blog/static/29281715201161911349440/

http://blog.csdn.net/mylzc/article/details/6771331 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值