android handler

来源:互联网 发布:apache压力测试 编辑:程序博客网 时间:2024/06/05 07:26

以下文字 摘自 老罗的 源代码分析一书 

Android 应用程序都是通过消息来驱动的。Android 应用程序的每一个线程在启动时,都可以首先在内部创建一个消息队列,然后进入到一个无线循环中,不断检查它的消息队列是否有新的消息需要处理。如果有新的消息需要处理,那么线程就会将它从消息队列中取出来,并且对它进行处理;否则,线程就会进入睡眠等待状态,直到有新的消息需要处理为止。这样就可以通过消息来驱动Android应用程序的执行了。

Android应用程序的消息处理机制是围绕消息队列来实现的。一个线程拥有了一个消息队列之后,就可以进入到一个消息循环中,同时 其他线程以及线程本身 可以往这个消息队列发送消息。

Android系统主要通过MessageQueue、Looper和Handler三个类来实现Android 应用程序的消息处理机制,其中,MessageQueue类用来描述消息队列;Looper 类用来创建消息队列,以及消息的轮询 。Handler类用来发送和处理消息。

java层 Looper 对象内都有一个MessageQueue类型的成员变量mQueue ,它指向一个MessageQueue对象。

通过Looper.prepare()或Looper.prepareMainLooper()来创建。注意 Looper类的静态成员函数prepareMainLooper 只能在Android 主线程中调用。但是主线程的Looper对象保存在一个独立的静态成员变量中,这样可以让其他线程通过Looper类的静态成员函数getMainLooper 来访问它,从而可以向从属于主线程looper对象的messageQueue消息队列里发送一些与ui操作相关的message啦!

prepare 时 就会创建一个包含有指向MessageQueue对象的变量的Looper对象

read the fucking source code 


ActivityThread main 方法 

 public static void main(String[] args) {        SamplingProfilerIntegration.start();        // CloseGuard defaults to true and can be quite spammy.  We        // disable it here, but selectively enable it later (via        // StrictMode) on debug builds, but using DropBox, not logs.        CloseGuard.setEnabled(false);        Environment.initForCurrentUser();        // Set the reporter for event logging in libcore        EventLogger.setReporter(new EventLoggingReporter());        Security.addProvider(new AndroidKeyStoreProvider());        Process.setArgV0("<pre-initialized>");        Looper.prepareMainLooper();        ActivityThread thread = new ActivityThread();        thread.attach(false);        if (sMainThreadHandler == null) {            sMainThreadHandler = thread.getHandler();        }        AsyncTask.init();        if (false) {            Looper.myLooper().setMessageLogging(new                    LogPrinter(Log.DEBUG, "ActivityThread"));        }        Looper.loop();        throw new RuntimeException("Main thread loop unexpectedly exited");    }


 public static void prepare() {        prepare(true);    }    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));    }

  public static void prepareMainLooper() {        prepare(false);        synchronized (Looper.class) {            if (sMainLooper != null) {                throw new IllegalStateException("The main Looper has already been prepared.");            }            sMainLooper = myLooper();        }    }
public final class MessageQueue {    // True if the message queue can be quit.    private final boolean mQuitAllowed;
主线程的消息队列不可以被终止

 private Looper(boolean quitAllowed) {        mQueue = new MessageQueue(quitAllowed);        mThread = Thread.currentThread();    }
可以看到looper类的构造方法里 有创建MessageQueue对象

handler.sendmessage/sendemptymessage ---> sendMessageAtTime

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

Looper.looper() 无限轮询 while(true) or  for(,,)

 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;            }           ------   =------            }            msg.target.dispatchMessage(msg);------            msg.recycle();        }    }

msg.target 是对应的handler 

handler的dispatchMessage()方法

 public void dispatchMessage(Message msg) {        if (msg.callback != null) {            handleCallback(msg);        } else {            if (mCallback != null) {                if (mCallback.handleMessage(msg)) {                    return;                }            }            handleMessage(msg);        }    }

子线程中创建Handler

protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);tv = new TextView(this);tv.setGravity(Gravity.CENTER);tv.setText("lalalala");tv.setTextColor(Color.BLACK);setContentView(tv);Log.i(TAG, "thread currendthread :: " + Thread.currentThread());//thread = new MyThread();//thread.start();//thread.handler.sendEmptyMessage(0);//NullPointExceptionHandlerThread  thread = new HandlerThread("childThreadName");thread.start();Handler childHandler  = new Handler(thread.getLooper()){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);Log.i(TAG, "current thread :: "+Thread.currentThread());}};childHandler.sendEmptyMessage(0);
<span style="white-space:pre">thread.quit();</span>//Quits the handler thread's looper.
}class MyThread extends Thread {public Handler handler ;@Overridepublic void run() {Looper.prepare();handler = new Handler(){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);Log.i(TAG, "current thread :: "+Thread.currentThread());}};Looper.loop();/*tv.post(new Runnable() {@Overridepublic void run() {tv.setText("success");}});*//*runOnUiThread(new Runnable() {@Overridepublic void run() {tv.setText("success");}});*/}}
HandlerThread 不用担心空指针异常 是因为 它的getLooper方法 

 public Looper getLooper() {        if (!isAlive()) {            return null;        }                // If the thread has been started, wait until the looper has been created.        synchronized (this) {            while (isAlive() && mLooper == null) {                try {                    wait();                } catch (InterruptedException e) {                }            }        }        return mLooper;    }

直到 run 方法 执行到looper 对象初始化  唤醒

 @Override    public void run() {        mTid = Process.myTid();        Looper.prepare();        synchronized (this) {            mLooper = Looper.myLooper();            notifyAll();        }        Process.setThreadPriority(mPriority);        onLooperPrepared();        Looper.loop();        mTid = -1;    }
handler callback 与 removeMessages

if (tvThread == null){tvThread = new Runnable(){int index = -1;String[] s = new String[]{ "  正在努力加载-", "  正在努力加载- -", "  正在努力加载- - -" };@Overridepublic void run(){index++;index = index % 3;tvNames.setText(s[index]);handler.postDelayed(tvThread, 300);}};}handler.postDelayed(tvThread, 100);
handler.removeCallbacks(tvThread);//结束thread

private Handler handler = new Handler(new Handler.Callback(){@Overridepublic boolean handleMessage(Message msg){if (isFinish){return true;//不再回调 下面的handleMessage方法}return false;}}){@Overridepublic void handleMessage(Message msg){
mHandler.removeMessages(0, null);

Remove any pending posts of messages with code 'what' and whose obj is 'object' that are in the message queue. Ifobject is null, all messages will be removed.


 /**     * Handle system messages here.     */    public void dispatchMessage(Message msg) {        if (msg.callback != null) {            handleCallback(msg);        } else {            if (mCallback != null) {                if (mCallback.handleMessage(msg)) {                    return;                }            }            handleMessage(msg);        }    }

public final class Message implements Parcelable {    public int what;    public int arg1;     public int arg2;    public Object obj;    /*package*/ int flags;    /*package*/ long when;        /*package*/ Bundle data;        /*package*/ Handler target;        /*package*/ Runnable callback;        // sometimes we store linked lists of these things    /*package*/ Message next;

 private static void handleCallback(Message message) {        message.callback.run();    }

   public interface Callback {        public boolean handleMessage(Message msg);    }


未完待续---


Multiple dex files define ------jar包 support v7 v4 版本不一致导致

0 0