Handler Looper( 三 )


抓重点:

Handler Looper

文章插图
Looper.prepareMainLooper();
找到类中关于这个方法的定义:
/*** Initialize the current thread as a looper, marking it as an* application's main looper. The main looper for your application* is created by the Android environment, so you should never need* to call this function yourself.See also: {@link #prepare()}*/public static void prepareMainLooper() {prepare(false);synchronized (Looper.class) {if (sMainLooper != null) {throw new IllegalStateException("The main Looper has already been prepared.");}sMainLooper = myLooper();}}
这里又会主动调用( )方法,通过注释也了解到我们不需要主动去创建UI线程的,系统自动会给我们创建好了,这里印证了前面的猜想 。
这里得出一个结论:
在主线程中可以直接创建对象,而在子线程中需要先调用.()才能创建对象 。
这里先不管是什么,暂时知道有这个东西,下面可以看一下如何发送消息 。
如何发送消息
这里就用到了第二种创建的方法:
Handler myHandler =new Handler() {public void handleMessage(Message msg) {switch (msg.what) {//根据参数进行操作break;}super.handleMessage(msg);}};//其他地方调用myHandler.sendMessage(xxx);
这里的其他地方调用指的就是在子线程里面,当我们在子线程里面执行完耗时操作之后如果需要传递一些数据给主线程,比如通知主线程更新UI之类的,就可以这么做:
finalHandler myHandler = new Handler() {public void handleMessage(Message msg) {switch (msg.what) {//根据参数进行操作}}};new Thread(new Runnable() {@Overridepublic void run() {Message msg=new Message();//what是用户自定义的识别码msg.what=1;//通过arg1和arg2可以给Message传递简单的int型数据msg.arg1=123;msg.arg2=456;//通过给obj赋值Object类型传递向Message传入任意数据msg.obj=null;myHandler.sendMessage(msg);}}).start();
当然除了传递这些简单数据之外类还能以方式携带数据:
Bundle bundle =new Bundle();bundle.putString("data", "data");message.setData(bundle);
我们看到这里是在子线程中调用了(msg)方法,然而我们却在主线程中使用( msg)接受消息,这之间一定发生了一些不可描述的事情,让我们来找找看,当然除了(msg)方法类还有许多其他发送消息的方法:
public final boolean sendMessage(Message msg){return sendMessageDelayed(msg, 0);}public final boolean sendEmptyMessage(int what){return sendEmptyMessageDelayed(what, 0);}public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {Message msg = Message.obtain();msg.what = what;return sendMessageDelayed(msg, delayMillis);}public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {Message msg = Message.obtain();msg.what = what;return sendMessageAtTime(msg, uptimeMillis);}.....
巧的是,这些方法无论转折多少次都走向了同一个方法:
/*** Enqueue a message into the message queue after all pending messages* before the absolute time (in milliseconds) uptimeMillis.* The time-base is {@link android.os.SystemClock#uptimeMillis}.* Time spent in deep sleep will add an additional delay to execution.* You will receive it in {@link #handleMessage}, in the thread attached* to this handler.* * @param uptimeMillis The absolute time at which the message should be*delivered, using the*{@link android.os.SystemClock#uptimeMillis} time-base.** @return Returns true if the message was successfully placed in to the *message queue.Returns false on failure, usually because the*looper processing the message queue is exiting.Note that a*result of true does not mean the message will be processed -- if*the looper is quit before the delivery time of the message*occurs then the message will be dropped.*/public boolean sendMessageAtTime(Message msg, long uptimeMillis) {MessageQueue queue = mQueue;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);}