国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

Handler源碼分析

2019-11-09 16:23:38
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
每個(gè)Handler都關(guān)聯(lián)了一個(gè)線程,每個(gè)線程都維護(hù)了一個(gè)消息隊(duì)列MessageQueue,這樣Handler實(shí)際上就關(guān)聯(lián)了一個(gè)消息隊(duì)列。可以通過(guò)handler將message和runnable對(duì)象發(fā)送到該handler所關(guān)聯(lián)線程的messagequeue中,然后該消息隊(duì)列一直在循環(huán)拿出一個(gè)message,并對(duì)其處理。

當(dāng)創(chuàng)建handler時(shí),該handler就綁定了當(dāng)前創(chuàng)建handler的線程。

一.在子線程使用Handler方式為:

Runnable runnable  = new Runnable(){

public void run(){

Looper.PRepare();

Handler handler = new Handler();

Looper.loop();

}

};

我們來(lái)分析一下,為什么要這么使用:

1. Looper.prepare();我們看看源碼是怎么實(shí)現(xiàn)的;

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));    }它實(shí)例化了一個(gè)Looper,并且和當(dāng)前線程綁定,也就是實(shí)例化一個(gè)Looper綁定到當(dāng)前子線程。

2.Handler handler = 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());            }        }        mLooper = Looper.myLooper();        if (mLooper == null) {            throw new RuntimeException(                "Can't create handler inside thread that has not called Looper.prepare()");        }        mQueue = mLooper.mQueue;        mCallback = callback;        mAsynchronous = async;    }這一段是實(shí)例化Handler。

3. Looper.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;        // Make sure the identity of this thread is that of the local process,        // and keep track of what that identity token actually is.        Binder.clearCallingIdentity();        final long ident = Binder.clearCallingIdentity();        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;            if (logging != null) {                logging.println(">>>>> Dispatching to " + msg.target + " " +                        msg.callback + ": " + msg.what);            }            msg.target.dispatchMessage(msg);            if (logging != null) {                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);            }            // Make sure that during the course of dispatching the            // identity of the thread wasn't corrupted.            final long newIdent = Binder.clearCallingIdentity();            if (ident != newIdent) {                Log.wtf(TAG, "Thread identity changed from 0x"                        + Long.toHexString(ident) + " to 0x"                        + Long.toHexString(newIdent) + " while dispatching to "                        + msg.target.getClass().getName() + " "                        + msg.callback + " what=" + msg.what);            }            msg.recycle();        }    }我們可以發(fā)現(xiàn)for(;;)的死循環(huán),queue.next()從MessageQueue隊(duì)列中取消息,

msg.target.dispatchMessage(msg); 其中msg.target一般是handler(下文會(huì)提到),然后由handler來(lái)分發(fā)消息。

 public void dispatchMessage(Message msg) {        if (msg.callback != null) {            handleCallback(msg);        } else {            if (mCallback != null) {                if (mCallback.handleMessage(msg)) {                    return;                }            }            handleMessage(msg);        }    }這里我看看到了熟悉的代碼handleMessage();先不看msg.callback和mCallback

當(dāng)我們實(shí)例化handler,重寫(xiě)handleMessage(),會(huì)在handlerMessage里面處理自己的邏輯(比如更新Ui等)

二:下面我們看看在UI線程使用handler的方式

Handler handler = new Handler();

handler.sendMessage();

這里有一個(gè)問(wèn)題:為什么UI線程沒(méi)有調(diào)用 Looper.prepare()和Looper.loop();

帶著這個(gè)問(wèn)題,我們來(lái)看看UI線程的源碼;

下面是ActivityThread的主函數(shù)入口:

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");    }我們可以看到主線程已經(jīng)創(chuàng)建了Looper,因此,在主線程使用handler時(shí)不需要Looper.prepare();

三 new Handler(Looper.getMainLooper()) 這種情況是,使用主線程的Looper

比如在子線程里面初始化handler,需要更新ui,那么就可以這么用。


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 通化市| 宜城市| 青冈县| 南昌市| 澎湖县| 扎兰屯市| 织金县| 伽师县| 五大连池市| 澳门| 黄浦区| 霞浦县| 鄂伦春自治旗| 沧州市| 沾益县| 绩溪县| 赞皇县| 岳池县| 海淀区| 漳平市| 石狮市| 织金县| 阿拉尔市| 平安县| 大埔县| 涟源市| 邵阳县| 临沂市| 兴安县| 平安县| 富民县| 商洛市| 枝江市| 伊宁县| 淮北市| 新源县| 永德县| 广宁县| 容城县| 安陆市| 贵南县|