1. 程式人生 > >Android原始碼分析——Looper,Messagequeue,Message,handler初始化及handler機制簡介

Android原始碼分析——Looper,Messagequeue,Message,handler初始化及handler機制簡介

private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }
直接上原始碼可見是個private的構造方法。可見單例模式痕跡明顯。肯定有對外的例項方法。接著看:
private static Looper sMainLooper;  // guarded by Looper.class
例項在類初始化的時候初始化了。只需要獲取即可。看看有哪些能獲取例項的方法:
/**
     * 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()}
     *///主執行緒用來例項化Looper的,你應該永遠也用不到它。
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }
prepareMainLooper很熟悉吧。對,就是它。主方法裡面用的就是它。當然註釋裡面說了,主執行緒用來例項化Looper的,你應該永遠也用不到它。然後提示你看prepare()

這裡第一句程式碼看看。

prepare(false)
這菊花雖然短,但是千萬不要忽略了。它就是那個萬惡的深藏著的Looper例項所在。
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));
    }
如果ThreadLocal.get()不為空,可能你會有疑問sThreadLocal究竟是什麼。後面我會認真考慮寫關於ThreadLocal的技術部落格的。現在只需要立即為一個儲存資料的物件,對外公開了set,get方法即可。
sThreadLocal.set(new Looper(quitAllowed));
這裡的quitallowed引數明顯一直沒變,是false會到最開始的私有的初始化函式private looper(boolean quitallowed)。發現其實到這兒我們的Looper例項化已經完事了。quitallowed是給Messagequeue物件例項化傳遞的一個引數罷了。既然這樣子,那就先放放,交給後面的Messagequeue去講它的例項化方法再提。

繞了一圈,再來談談輪詢loop()方法。

looper().loop()輪詢方法

先把loop()原始碼奉上。在哪用到就再提一句吧,每次Looper例項化完,必須緊跟著它。因為首先要有這個輪詢器(例項化),然後再將輪訓器運轉起來loop()。

/**
     * Run the message queue in this thread. Be sure to call
     * {@link #quit()} to end the 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.recycleUnchecked();
        }
    }
現在可以一行行看程式碼了,先判斷看看有沒有輪訓器?有則繼續,沒有就拋異常。所以,當你看到下面這個異常的時候,你就知道,你肯定沒寫輪訓器。
final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
不要問我me是什麼,me就是Looper例項。

相關推薦

Android原始碼分析——LooperMessagequeueMessagehandler初始handler機制簡介

private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }直接上原始碼可見是個private的構造

Netflix Eureka原始碼分析(7)——eureka client啟動環境初始流程

eureka-examples,有一個類,ExampleEurekaClient,就是一個自帶的例子,如果是一個eureka服務,一定會有一個eureka client,服務例項啟動的時候,一定會啟動eureka client,eureka client去向eureka se

Spring原始碼分析(二)-Spring IoC容器的初始No.2

Spring原始碼分析(一)-Spring IoC容器的初始化No.1中已經分析了Bean的載入過程,本章將分析Bean的例項化過程 本章圍繞refresh().finishBeanFactoryInitialization(beanFactory)方法,

AFNetworking3.1.0原始碼分析(四)詳解AFHTTPRequestSerializer 之初始方法

1:類圖介紹 在AFHTTPSessionManager 初始化方法中可以看到 AFNetworking 預設使用的網路請求序列化類是AFHTTPRequestSerializer,一下是關於它的類圖: 2:類功能分析:  一:初始化函式: - (instancetyp

Spring原始碼分析(二)-Spring IoC容器的初始No.1

Spring IoC容器的初始化 Spring原始碼分析(一)中提到了很多類,比如BeanDefinition、BeanDefinitionReader、BeanDefintionParser、BeanWrapper等都是ApplicationContext中

Netty原始碼分析之ChannelPipeline(一)—ChannelPipeline的構造與初始

Netty中ChannelPipeline實際上類似與一條資料管道,負責傳遞Channel中讀取的訊息,它本質上是基於責任鏈模式的設計與實現,無論是IO事件的攔截器,還是使用者自定義的ChannelHandler業務邏輯都做為一個個節點被新增到任務鏈上。 一、ChannelPipeline的設計與構成 &

kubeadm原始碼分析(內含kubernetes離線包三步安裝)_Kubernetes中文社群

k8s離線安裝包 三步安裝,簡單到難以置信 kubeadm原始碼分析 說句實在話,kubeadm的程式碼寫的真心一般,質量不是很高。 幾個關鍵點來先說一下kubeadm乾的幾個核心的事: kubeadm 生成證書在/etc/kubernetes/pki目錄下 kubeadm 生成static

Android訊息處理機制、Hanlder機制HandlerLooperMessageQueueMessage

·前言長久以來,我使用Hanlder僅限於它的基本使用:post 和 sendMessage而對於Hanlder的原理和訊息處理機制並不清楚。找了兩篇比較深入的部落格:學習了一下,又對照了原始碼,小有收穫,俗話說“好記性不如爛筆頭”,所以做一下筆記,總結一下,方便以後回顧。·

Android原始碼分析-訊息佇列和Looper

轉載請註明出處:http://blog.csdn.net/singwhatiwanna/article/details/17361775 前言 上週對Android中的事件派發機制進行了分析,這次博主要對訊息佇列和Looper的原始碼進行簡單的分析。大家耐心看下去,其實訊息

基於android原始碼基礎的API文件製作CHM格式製作

步驟一:生成doc的index.html檔案 1.device\mstar\common\libraries\tvapi\java下新建package.txt,,將此目錄下的子包,全部列出來,放入package.txt,中 如: com.mstar.android.tvap

Android原始碼分析之為什麼在onCreate() 和 onResume() 獲取不到 View 的寬高

轉載自:https://www.jianshu.com/p/d7ab114ac1f7 先來看一段很熟悉的程式碼,可能在最開始接觸安卓的時候,大部分人都寫過的一段程式碼;即嘗試在 onCreate() 和 onResume() 方法中去獲取某個 View 的寬高資訊: 但是列印輸出後,我們會發

Android原始碼分析-Activity的啟動過程

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android原始碼分析-全面理解Context

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android原始碼分析Activity載入流程

從Android原始碼分析Activity載入流程 概述:startActivity->startActivityForResult->Instrumentation::execStartActivity->scheduleLaunchActivi

寫一個手機類屬性:品牌brand,價格price 行為:打電話Call發簡訊Message打遊戲Game 要用到this和Private的知識點

初寫手機類 這個程式是初步的程式,還有很多細節沒補上,等到學到後面再逐漸完善了 class Demond_Phone { public static void main(String[] args) { Phone p1 = new Phone();

Android原始碼分析—帶你認識不一樣的AsyncTask(串並行)

前言 什麼是AsyncTask,相信搞過android開發的朋友們都不陌生。AsyncTask內部封裝了Thread和Handler,可以讓我們在後臺進行計算並且把計算的結果及時更新到UI上,而這些正是Thread+Handler所做的事情,沒錯,AsyncTask

Android原始碼分析之簡單工廠模式

模式的定義 簡單工廠模式又稱為靜態方法工廠模式,是由一個工廠物件決定建立哪一個產品類的例項。 使用場景 客戶端需要建立物件、隱藏物件的建立過程,且目標物件型別數量不多的情況下,可以考慮使用簡單工廠模式。 UML類圖 角色介紹 Product 產品的通用介面,定義產

android 原始碼分析開啟mic

1、demo   AudioManager  audioManager  =  (AudioManager)getSystemService("audio");   audioManager.setMode(AudioManager.STREAM

React Native 4 for Android原始碼分析 一《JNI智慧指標之介紹篇》

導讀 React Native 釋出以來將近一年多了,也被抄的火爆到不行,包括RN的中文網和各種資料也很多,加之SE5,Se6語法升級,學習成本並不在RN環境搭建和入門,關鍵還是對JS的掌握入門,不管你是用Native開發,h5開發,還是React

中國象棋android原始碼分析

        大家好,今天我給大家分享一箇中國象棋的Android遊戲原始碼。先來一張圖片看看效果。 1、原始碼結構         所有類都放置到com.bn.chess包裡. 2、類及類關係介紹 (1)Chess_DJB_Activity->Welcom