Android中的消息机制
生活随笔
收集整理的這篇文章主要介紹了
Android中的消息机制
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Android 中的消息機制其實就是指的是 Handler 消息機制以及附帶的 Looper 和 MessageQueue 的工作流程。
1.Android 為什么提供Handler?
- 解決子線程不能訪問 UI 的問題 在 ViewRootImpl 中有一個checkThread() 方法:
2. 為什么子線程不能訪問UI呢?
- Android 的 UI 控件不是線程安全的,如果在多線程中并發訪問 UI 控件會導致 UI 控件處于不可預期的狀態
3.那為什么不給UI控件加上鎖機制呢?
- 加鎖會增加UI邏輯復雜性
- 鎖機制會降低線程訪問UI的效率
4.Handler 的工作原理
5.ThreadLocal
Looper.java
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.java
class Thread{/* ThreadLocal values pertaining to this thread. This map is maintained* by the ThreadLocal class. */ThreadLocal.ThreadLocalMap threadLocals = null; }復制代碼threadLocals 屬于 Thread 里的一個變量
ThreadLocalMap getMap(Thread t) {return t.threadLocals;} 復制代碼void createMap(Thread t, T firstValue) {t.threadLocals = new ThreadLocalMap(this, firstValue);} 復制代碼public void set(T value) {//獲取當前的線程對象Thread t = Thread.currentThread();//getMap(t) 我們就知道了就是獲取當前線程里的 //threadLocals 變量 ,//類型是ThreadLocal.ThreadLocalMap類型ThreadLocalMap map = getMap(t);//判斷取出的是否為空,第一次應該為空if (map != null)//第二次不為空,將key:ThreadLocal;value:Looper存入map.set(this, value);else//為null時,創建ThreadLocalMap對象,并且將值與線程存入createMap(t, value);} 復制代碼那么我們需要知道 ThreadLocalMap 是如何存儲的?
//ThreadLocal 靜態內部類 static class ThreadLocalMap {static class Entry extends WeakReference<ThreadLocal<?>> {/** The value associated with this ThreadLocal. */Object value;Entry(ThreadLocal<?> k, Object v) {super(k);value = v;}}/*** The initial capacity -- MUST be a power of two.*/private static final int INITIAL_CAPACITY = 16;/*** The table, resized as necessary.* table.length MUST always be a power of two.*/private Entry[] table;xxx ....ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {table = new Entry[INITIAL_CAPACITY];int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);table[i] = new Entry(firstKey, firstValue);size = 1;setThreshold(INITIAL_CAPACITY);}/*** Set the value associated with key.** @param key the thread local object* @param value the value to be set*/private void set(ThreadLocal<?> key, Object value) {// We don't use a fast path as with get() because it is at// least as common to use set() to create new entries as// it is to replace existing ones, in which case, a fast// path would fail more often than not.Entry[] tab = table;int len = tab.length;//取出那個下標int i = key.threadLocalHashCode & (len-1);for (Entry e = tab[i];e != null;e = tab[i = nextIndex(i, len)]) {ThreadLocal<?> k = e.get();if (k == key) {e.value = value;return;}if (k == null) {replaceStaleEntry(key, value, i);return;}}tab[i] = new Entry(key, value);int sz = ++size;if (!cleanSomeSlots(i, sz) && sz >= threshold)rehash();} }復制代碼6. 主線程 的 Looper 是何時創建的?
在 ActivityThread 的 main 方法中創建的,一起來看下:
public static void main(String[] args) {Looper.prepareMainLooper();xxx....Looper.loop(); } 復制代碼Looper.prepareMainLooper();
public static void prepareMainLooper() {prepare(false);synchronized (Looper.class) {if (sMainLooper != null) {throw new IllegalStateException("The main Looper has already been prepared.");}sMainLooper = myLooper();}}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));} 復制代碼prepare 方法中又創建threadLocal與Looper的關聯 , 而且加了判斷,說明一個線程只能有一個Looper,而后創建了 Looper 的實例。 Looper 構造方法
private Looper(boolean quitAllowed) {mQueue = new MessageQueue(quitAllowed);mThread = Thread.currentThread();} 復制代碼創建了 MessageQueue 實例,獲取當前的線程。
而在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;} 復制代碼直接取出當前線程的 Looper--mLooper 和 Looper 中的 MessageQueue 對象。后面就是發消息,消息入隊,Looper取出消息,進而調用 handler 的 handleMessage 方法。
看書,隨筆記。如有問題,可指出。
總結
以上是生活随笔為你收集整理的Android中的消息机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一步步教你轻松学K-means聚类算法
- 下一篇: cpu核心数的线程数