Android 執行緒與訊息 機制 15問15答

希爾瓦娜斯女神發表於2016-02-15

1.handler,looper,messagequeue三者之間的關係以及各自的角色?

答:MessageQueue就是儲存訊息的載體,Looper就是無限迴圈查詢這個載體裡是否還有訊息。Handler就是建立的時候 會使用looper來構建這個訊息迴圈。

handler的主要功能就是 將一個任務切換到某個指定的執行緒中去執行。

 

2.為何android 無法在子執行緒更新ui?

答:都知道 更新ui 實際工作都是在viewrootimpl這個類裡面去做的。他的原始碼裡有下面這樣一個函式:

1   void checkThread() {
2         if (mThread != Thread.currentThread()) {
3             throw new CalledFromWrongThreadException(
4                     "Only the original thread that created a view hierarchy can touch its views.");
5         }
6     }
View Code

在原始碼裡 就限定了 你這個子執行緒是不能訪問ui的。只有主執行緒能訪問ui。原因其實很簡單,你要是允許子執行緒也操作ui,那就得給ui 加上鎖機制,

鎖機制就太影響效率了。所以為了效率 就控制開發者 只能在主執行緒上訪問ui。

 

3.簡單概述一下Handler的工作原理?

答:其實很簡單,關係理順了就可以了。首先要明白 handler要建立成功 必須有一個前提條件 就是建立handler的執行緒 必須有looper。不然就會報錯。

  handler使用方法 一般就2個 post 傳一個runnable 或者send一個訊息。注意的是post方法 最後其實也是呼叫的send方法。這個send方法

  最終會呼叫messagequeue的enqueuemessage方法,就是把訊息放入佇列中。與此同時looper 是一個無限迴圈 會無限從這個訊息佇列裡面

     取訊息,取出來以後 訊息中的runnable 或者 handler的handlerMessage方法就會被呼叫了。這個地方有一個關鍵的地方就在於 我們的looper

     是執行在 建立handler的執行緒中的。所以looper在處理訊息的時候 會把這個訊息也執行在 建立handler的所線上程中。想明白這點 就明白了

  handler的執行機制了。

 

4.簡單介紹下threadLocal?

答:這個東西 在looper activitythread 以及ams中 都有大量應用。其實作用就是在指定的執行緒中儲存資料。當你希望有一個資料 在不同執行緒中 都能獨立儲存自己的獨立值

互相不干擾互相不影響的時候 就可以使用threadlocal了。他的作用域僅限於執行緒。

給個例子

 1 package com.example;
 2 
 3 public class MyClass {
 4 
 5 
 6     public static void main(String[] args) {
 7 
 8         ThreadLocal<Integer> mIntegerThreadLocal = new ThreadLocal<Integer>();
 9         mIntegerThreadLocal.set(0);
10         //輸出結果為main thread threadlocal==0
11         System.out.println("main thread threadlocal==" + mIntegerThreadLocal.get());
12 
13         new Thread("Thread 1") {
14             @Override
15             public void run() {
16                 mIntegerThreadLocal.set(0);
17                 mIntegerThreadLocal.set(mIntegerThreadLocal.get() + 2);
18                 //輸出結果為 Thread 1 threadlocal==2
19                 System.out.println("Thread 1 threadlocal==" + mIntegerThreadLocal.get());
20             }
21         }.start();
22 
23         new Thread("Thread 2") {
24             @Override
25             public void run() {
26                 //這裡就會報空指標錯誤了 因為mIntegerThreadLocal 在這個執行緒中沒有初始化他的值所以是null pointer
27                 mIntegerThreadLocal.set(mIntegerThreadLocal.get() + 2);
28                 System.out.println("Thread 1 threadlocal==" + mIntegerThreadLocal.get());
29             }
30         }.start();
31 
32 
33     }
34 }
View Code

 

5.從原始碼的角度 闡述threadlocal的原理?

答:

  1 //首先我們可以看到 這是一個泛型, 我們的分析 建立在java 1.8 的基礎上 其他java版本這裡實現都有各自的不同 有興趣的可以自己自行分析
  2 public class ThreadLocal<T> {
  3 
  4 //然後我們看一下 set方法
  5 public void set(T value) {
  6         //先取出當前的thread
  7         Thread t = Thread.currentThread();
  8         //然後從getMap方法裡 取t 也就是當前這個thread的資料 , ThreadLocalMap是一個靜態內部類 你可以把他看做 儲存threadlocal資料的一個載體
  9         ThreadLocalMap map = getMap(t);
 10         //如果取出來是空 那就給他set一個值進去 也就是更新這個threadlocal的值
 11         if (map != null)
 12             map.set(this, value);
 13         else
 14             //否則就建立一個ThreadLocalMap的值
 15             createMap(t, value);
 16     }
 17 
 18 //getMap就是取出這個執行緒的threadLocals 如果這個值為null 就說明這個執行緒還從來沒有使用過threadlocal物件
 19 ThreadLocalMap getMap(Thread t) {
 20         return t.threadLocals;
 21     }
 22 
 23 
 24 
 25 //我們可以先跟蹤createMap方法 也就是建立ThreadLocalMap的流程
 26 void createMap(Thread t, T firstValue) {
 27         //這裡thread的threadLocals 的值 就是在這裡被賦值了,也就是ThreadLocalMap物件
 28         //可以明確 一個執行緒T,就有一個唯一的ThreadLocalMap物件,裡面儲存的就是
 29         //這個執行緒裡的th物件。也就是threadlocal
 30         t.threadLocals = new ThreadLocalMap(this, firstValue);
 31 }
 32 
 33 //可以看到是用這個構造方法來構造的
 34  ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
 35             //首先是創造了一個table陣列
 36             table = new Entry[INITIAL_CAPACITY];
 37             //然後根據一定的演算法 計算出來 我們傳進來的這個ThreadLocal 應該在table陣列裡的位置 也就是i
 38             int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
 39             //然後把i位置上對應的值 賦值進去,有點類似於hashmap的流程 
 40             table[i] = new Entry(firstKey, firstValue);
 41             size = 1;
 42             setThreshold(INITIAL_CAPACITY);
 43             //所以這裡要明確的就是一個th的值 在table陣列裡 就對應著一個位置,
 44   }
 45 
 46 
 47 
 48 //簡單瀏覽一下Entry的資料結構
 49         static class Entry extends WeakReference<ThreadLocal<?>> {
 50             /** The value associated with this ThreadLocal. */
 51             Object value;
 52 
 53             Entry(ThreadLocal<?> k, Object v) {
 54                 super(k);
 55                 value = v;
 56             }
 57         }
 58 
 59 
 60 
 61 
 62 //前面我們簡單分析了 threadlocal 第一次被建立時的 儲存過程
 63 //然後看我們的set方法 也就是更新threadlocal的過程
 64 //這裡的邏輯很簡單  當某個執行緒t 已經有了threadLocals的值以後 第二次再呼叫set方法 就會走到這裡了。第一次呼叫set方法 可以看上面的createMap流程
 65 //當第二次或者第n次呼叫set方法 以後 就會根據th的值 在table裡遍歷 找到這個th對應的值,因為一個執行緒t 可能有n個不同的th變數。
 66 //這個函式就是根據你傳進去的th變數 找到對應的位置 來更新他的值
 67  private void set(ThreadLocal<?> key, Object value) {
 68 
 69             // We don't use a fast path as with get() because it is at
 70             // least as common to use set() to create new entries as
 71             // it is to replace existing ones, in which case, a fast
 72             // path would fail more often than not.
 73 
 74             Entry[] tab = table;
 75             int len = tab.length;
 76             //通過我們傳進去的theradlocal 取出table陣列裡的值 table[i]
 77             int i = key.threadLocalHashCode & (len-1);
 78 
 79             
 80             for (Entry e = tab[i];
 81                  e != null;
 82                  e = tab[i = nextIndex(i, len)]) {
 83                 ThreadLocal<?> k = e.get();
 84 
 85                 if (k == key) {
 86                     e.value = value;
 87                     return;
 88                 }
 89 
 90                 if (k == null) {
 91                     replaceStaleEntry(key, value, i);
 92                     return;
 93                 }
 94             }
 95 
 96             tab[i] = new Entry(key, value);
 97             int sz = ++size;
 98             if (!cleanSomeSlots(i, sz) && sz >= threshold)
 99                 rehash();
100         }
101 
102 
103 //再來看一下 threadlocal的get方法
104 public T get() {
105         Thread t = Thread.currentThread();
106         //先看看當前執行緒t的threadLocals 有沒有被賦值
107         ThreadLocalMap map = getMap(t);
108         //如果不等於null 也就是說當前執行緒的threadLocals 值已經有了 那我們就直接取對應的value值即可
109         if (map != null) {
110             ThreadLocalMap.Entry e = map.getEntry(this);
111             if (e != null) {
112                 @SuppressWarnings("unchecked")
113                 T result = (T)e.value;
114                 return result;
115             }
116         }
117         //否則我們就給他返回一個初始值 這個初始值 你跟進去看原始碼就會發現是null了
118         return setInitialValue();
119     }
120 
121   //簡單分析了 threadlocal 的set和get方法 總結起來就是 他的set和get操作 就是以當前執行緒為key 取對應的值。可以簡單類比想象成是一個雜湊表 這個雜湊表的key就是執行緒。
122   //你要操作th的值 就得把當前的執行緒t 傳到這個表裡面 然後取得對應執行緒t的 對應value 即可。
View Code

 

6.從原始碼的角度 闡述MessageQueue的原理?

答:

  1  //我們首先來看一下enqueueMessage的操作 這個操作主要是對訊息佇列進行一個插入訊息的操作
  2  //這個你細細看一下 就是一個很簡單的單連結串列的操作罷了,隨意雖然這東西 叫訊息佇列 但是其實跟佇列並沒有什麼關係
  3  //內部實現為一個連結串列 
  4  boolean enqueueMessage(Message msg, long when) {
  5         if (msg.target == null) {
  6             throw new IllegalArgumentException("Message must have a target.");
  7         }
  8         if (msg.isInUse()) {
  9             throw new IllegalStateException(msg + " This message is already in use.");
 10         }
 11 
 12         synchronized (this) {
 13             if (mQuitting) {
 14                 IllegalStateException e = new IllegalStateException(
 15                         msg.target + " sending message to a Handler on a dead thread");
 16                 Log.w(TAG, e.getMessage(), e);
 17                 msg.recycle();
 18                 return false;
 19             }
 20 
 21             msg.markInUse();
 22             msg.when = when;
 23             //mMessages 這個你可以把他看成是單連結串列的表頭
 24             Message p = mMessages;
 25             boolean needWake;
 26             //當你第一次往訊息佇列裡 插入訊息的時候,表頭就變成了你第一次傳進來的這個訊息
 27             if (p == null || when == 0 || when < p.when) {
 28                 // New head, wake up the event queue if blocked.
 29                 msg.next = p;
 30                 mMessages = msg;
 31                 needWake = mBlocked;
 32             } else {
 33                 // Inserted within the middle of the queue.  Usually we don't have to wake
 34                 // up the event queue unless there is a barrier at the head of the queue
 35                 // and the message is the earliest asynchronous message in the queue.
 36                 needWake = mBlocked && p.target == null && msg.isAsynchronous();
 37 
 38                 //如果不是第一次傳訊息  
 39                 //簡單的連結串列操作不多做分析
 40                 Message prev;
 41                 for (;;) {
 42                     prev = p;
 43                     p = p.next;
 44                     if (p == null || when < p.when) {
 45                         break;
 46                     }
 47                     if (needWake && p.isAsynchronous()) {
 48                         needWake = false;
 49                     }
 50                 }
 51                 msg.next = p; // invariant: p == prev.next
 52                 prev.next = msg;
 53             }
 54 
 55             // We can assume mPtr != 0 because mQuitting is false.
 56             if (needWake) {
 57                 nativeWake(mPtr);
 58             }
 59         }
 60         return true;
 61     }
 62 
 63 
 64 //next方法就是從訊息佇列中 取出一個訊息 然後刪除他
 65      Message next() {
 66         // Return here if the message loop has already quit and been disposed.
 67         // This can happen if the application tries to restart a looper after quit
 68         // which is not supported.
 69         final long ptr = mPtr;
 70         if (ptr == 0) {
 71             return null;
 72         }
 73 
 74         int pendingIdleHandlerCount = -1; // -1 only during first iteration
 75         int nextPollTimeoutMillis = 0;
 76         //注意看這個for迴圈 括號體內是沒有break語句的 也就是說這個迴圈 永遠不會退出!如果這個訊息佇列裡沒有訊息的話
 77         //這個next方法 就阻塞了 因為你仔細看 這個裡面沒有break語句 只有當取出訊息的時候才會return一個message回去
 78         //只有這種情況成立的時候 這個迴圈才會結束 這個函式才會結束,除此之外 這個函式就永遠阻塞在這裡
 79         for (;;) {
 80             if (nextPollTimeoutMillis != 0) {
 81                 Binder.flushPendingCommands();
 82             }
 83 
 84             nativePollOnce(ptr, nextPollTimeoutMillis);
 85 
 86             synchronized (this) {
 87                 // Try to retrieve the next message.  Return if found.
 88                 final long now = SystemClock.uptimeMillis();
 89                 Message prevMsg = null;
 90                 Message msg = mMessages;
 91                 if (msg != null && msg.target == null) {
 92                     // Stalled by a barrier.  Find the next asynchronous message in the queue.
 93                     do {
 94                         prevMsg = msg;
 95                         msg = msg.next;
 96                     } while (msg != null && !msg.isAsynchronous());
 97                 }
 98                 if (msg != null) {
 99                     if (now < msg.when) {
100                         // Next message is not ready.  Set a timeout to wake up when it is ready.
101                         nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
102                     } else {
103                         // Got a message.
104                         mBlocked = false;
105                         if (prevMsg != null) {
106                             prevMsg.next = msg.next;
107                         } else {
108                             mMessages = msg.next;
109                         }
110                         msg.next = null;
111                         if (DEBUG) Log.v(TAG, "Returning message: " + msg);
112                         msg.markInUse();
113                         return msg;
114                     }
115                 } else {
116                     // No more messages.
117                     nextPollTimeoutMillis = -1;
118                 }
119 
120                 // Process the quit message now that all pending messages have been handled.
121                 if (mQuitting) {
122                     dispose();
123                     return null;
124                 }
125 
126                 // If first time idle, then get the number of idlers to run.
127                 // Idle handles only run if the queue is empty or if the first message
128                 // in the queue (possibly a barrier) is due to be handled in the future.
129                 if (pendingIdleHandlerCount < 0
130                         && (mMessages == null || now < mMessages.when)) {
131                     pendingIdleHandlerCount = mIdleHandlers.size();
132                 }
133                 if (pendingIdleHandlerCount <= 0) {
134                     // No idle handlers to run.  Loop and wait some more.
135                     mBlocked = true;
136                     continue;
137                 }
138 
139                 if (mPendingIdleHandlers == null) {
140                     mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
141                 }
142                 mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
143             }
144 
145             // Run the idle handlers.
146             // We only ever reach this code block during the first iteration.
147             for (int i = 0; i < pendingIdleHandlerCount; i++) {
148                 final IdleHandler idler = mPendingIdleHandlers[i];
149                 mPendingIdleHandlers[i] = null; // release the reference to the handler
150 
151                 boolean keep = false;
152                 try {
153                     keep = idler.queueIdle();
154                 } catch (Throwable t) {
155                     Log.wtf(TAG, "IdleHandler threw exception", t);
156                 }
157 
158                 if (!keep) {
159                     synchronized (this) {
160                         mIdleHandlers.remove(idler);
161                     }
162                 }
163             }
164 
165             // Reset the idle handler count to 0 so we do not run them again.
166             pendingIdleHandlerCount = 0;
167 
168             // While calling an idle handler, a new message could have been delivered
169             // so go back and look again for a pending message without waiting.
170             nextPollTimeoutMillis = 0;
171         }
172     }
View Code

 

7.從原始碼的角度 闡述Looper的原理?

答:

 1 //這是一個典型的在子執行緒裡建立handler的操作 我們看到在這裡建立handler的時候 我們做了2步操作
 2 //第一步是建立looper 第二步是開啟訊息迴圈。
 3         new Thread(){
 4             @Override
 5             public void run() {
 6                Looper.prepare();
 7                 Handler handler=new Handler();
 8                 Looper.loop();
 9             }
10         }.start();
11 
12 
13 //我們主要看loop 這個方法 因為只有呼叫了這個方法 訊息迴圈才真正啟動
14 
15  public static void loop() {
16         final Looper me = myLooper();
17         if (me == null) {
18             throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
19         }
20         final MessageQueue queue = me.mQueue;
21 
22         // Make sure the identity of this thread is that of the local process,
23         // and keep track of what that identity token actually is.
24         Binder.clearCallingIdentity();
25         final long ident = Binder.clearCallingIdentity();
26         //可以看到 這又是一個死迴圈
27         for (;;) {
28             Message msg = queue.next(); // might block
29             //唯一跳出迴圈的方式 就是這個msg 為null 也就是訊息佇列的next方法返回null
30             //而next方法返回null的唯一方法 就是呼叫looper的quit方法 所以這裡就能得知
31             //looper你必須手動幫他退出 否則loop方法就是無限迴圈下去
32             if (msg == null) {
33                 // No message indicates that the message queue is quitting.
34                 return;
35             }
36 
37             // This must be in a local variable, in case a UI event sets the logger
38             Printer logging = me.mLogging;
39             if (logging != null) {
40                 logging.println(">>>>> Dispatching to " + msg.target + " " +
41                         msg.callback + ": " + msg.what);
42             }
43 
44             //這個地方msg 就是發過來的訊息,也就是訊息佇列那個連結串列裡面儲存的message ,target就是傳送這條訊息的handler物件。
45             //所以這裡就能明白最終訊息 還是交給handler的dispatchmessage方法來處理的 只不過這個dispatchmessage方法 是在建立handler
46             //的時候 所使用的looper去執行的 而我們建立looper的時機 正是線上程的run方法裡,所以 程式碼邏輯的最終執行就是在建立handler
47             //的那個執行緒裡
48             msg.target.dispatchMessage(msg);
49 
50             if (logging != null) {
51                 logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
52             }
53 
54             // Make sure that during the course of dispatching the
55             // identity of the thread wasn't corrupted.
56             final long newIdent = Binder.clearCallingIdentity();
57             if (ident != newIdent) {
58                 Log.wtf(TAG, "Thread identity changed from 0x"
59                         + Long.toHexString(ident) + " to 0x"
60                         + Long.toHexString(newIdent) + " while dispatching to "
61                         + msg.target.getClass().getName() + " "
62                         + msg.callback + " what=" + msg.what);
63             }
64 
65             msg.recycleUnchecked();
66         }
67     }
View Code

 

8.使用looper需要注意什麼?

答:不需要的時候 記得終止looper。因為如果你手動處理完畢你需要的業務邏輯以後 如果不呼叫quit或者quitsafely方法 looper的loop方法就一直執行下去,永遠不停止,你這個子執行緒永遠都結束不了。

很容易就記憶體洩露 或者其他錯誤,所以我們要牢記 當子執行緒使用looper的時候 業務處理完畢 記得手動關閉looper。

 

9.從原始碼的角度 闡述handler的工作原理?

答:

 1  //handler有2個發訊息的方法一個是post 一個是send 只不過post最終也是走的send
 2  //可以看出來 handler傳送訊息 其實就是往訊息佇列裡放了一個message罷了
 3  public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
 4         MessageQueue queue = mQueue;
 5         if (queue == null) {
 6             RuntimeException e = new RuntimeException(
 7                     this + " sendMessageAtTime() called with no mQueue");
 8             Log.w("Looper", e.getMessage(), e);
 9             return false;
10         }
11         return enqueueMessage(queue, msg, uptimeMillis);
12     }
13 
14 
15 
16     //這是handler處理訊息的邏輯 注意這個方法的執行 實在looper所屬的執行緒中。
17     public void dispatchMessage(Message msg) {
18     //msg的callback就是runnable物件
19         if (msg.callback != null) {
20           //如果你是post方法 實際上handler就是呼叫你post傳進去的那個runnable的run方法而已。
21             handleCallback(msg);
22         } else {
23             //這個實際上就是提供一個 不用派生handler子類時 建立handler物件的方法 雖然我們實際使用中很少使用這種方式
24             if (mCallback != null) {
25                 if (mCallback.handleMessage(msg)) {
26                     return;
27                 }
28             }
29             handleMessage(msg);
30         }
31     }
32 
33 
34     private static void handleCallback(Message message) {
35         message.callback.run();
36     }
37 
38     public interface Callback {
39         public boolean handleMessage(Message msg);
40     }
41 
42 
43 
44 
45 //看這個建構函式 就能明白為啥建立handler的時候必須得有looper了 所以再一次強調
46 //在子執行緒中建立handler的前提條件 是一定得有looper,
47     public Handler(Callback callback, boolean async) {
48         if (FIND_POTENTIAL_LEAKS) {
49             final Class<? extends Handler> klass = getClass();
50             if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
51                     (klass.getModifiers() & Modifier.STATIC) == 0) {
52                 Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
53                     klass.getCanonicalName());
54             }
55         }
56 
57         mLooper = Looper.myLooper();
58         if (mLooper == null) {
59             throw new RuntimeException(
60                 "Can't create handler inside thread that has not called Looper.prepare()");
61         }
62         mQueue = mLooper.mQueue;
63         mCallback = callback;
64         mAsynchronous = async;
65     }
View Code

 

10.android裡 主執行緒的訊息迴圈是怎樣實現的?

答:

  1  
  2 //可以看activitythread 的原始碼
  3  public static void main(String[] args) {
  4         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
  5         SamplingProfilerIntegration.start();
  6         // CloseGuard defaults to true and can be quite spammy.  We
  7         // disable it here, but selectively enable it later (via
  8         // StrictMode) on debug builds, but using DropBox, not logs.
  9         CloseGuard.setEnabled(false);
 10         Environment.initForCurrentUser();
 11         // Set the reporter for event logging in libcore
 12         EventLogger.setReporter(new EventLoggingReporter());
 13         AndroidKeyStoreProvider.install();
 14         // Make sure TrustedCertificateStore looks in the right place for CA certificates
 15         final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
 16         TrustedCertificateStore.setDefaultUserDirectory(configDir);
 17         Process.setArgV0("<pre-initialized>");
 18         //建立了主執行緒的looper
 19         Looper.prepareMainLooper();
 20         ActivityThread thread = new ActivityThread();
 21         thread.attach(false);
 22         if (sMainThreadHandler == null) {
 23             sMainThreadHandler = thread.getHandler();
 24         }
 25         if (false) {
 26             Looper.myLooper().setMessageLogging(new
 27                     LogPrinter(Log.DEBUG, "ActivityThread"));
 28         }
 29         // End of event ActivityThreadMain.
 30         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
 31         //開啟了主執行緒的訊息迴圈
 32         Looper.loop();
 33         throw new RuntimeException("Main thread loop unexpectedly exited");
 34     }
 35 }
 36 
 37 //這個就是主執行緒 的handler 四大元件的啟動 停止過程 都在這個裡面定義好了
 38 
 39 private class H extends Handler {
 40         public static final int LAUNCH_ACTIVITY         = 100;
 41         public static final int PAUSE_ACTIVITY          = 101;
 42         public static final int PAUSE_ACTIVITY_FINISHING= 102;
 43         public static final int STOP_ACTIVITY_SHOW      = 103;
 44         public static final int STOP_ACTIVITY_HIDE      = 104;
 45         public static final int SHOW_WINDOW             = 105;
 46         public static final int HIDE_WINDOW             = 106;
 47         public static final int RESUME_ACTIVITY         = 107;
 48         public static final int SEND_RESULT             = 108;
 49         public static final int DESTROY_ACTIVITY        = 109;
 50         public static final int BIND_APPLICATION        = 110;
 51         public static final int EXIT_APPLICATION        = 111;
 52         public static final int NEW_INTENT              = 112;
 53         public static final int RECEIVER                = 113;
 54         public static final int CREATE_SERVICE          = 114;
 55         public static final int SERVICE_ARGS            = 115;
 56         public static final int STOP_SERVICE            = 116;
 57         public static final int CONFIGURATION_CHANGED   = 118;
 58         public static final int CLEAN_UP_CONTEXT        = 119;
 59         public static final int GC_WHEN_IDLE            = 120;
 60         public static final int BIND_SERVICE            = 121;
 61         public static final int UNBIND_SERVICE          = 122;
 62         public static final int DUMP_SERVICE            = 123;
 63         public static final int LOW_MEMORY              = 124;
 64         public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
 65         public static final int RELAUNCH_ACTIVITY       = 126;
 66         public static final int PROFILER_CONTROL        = 127;
 67         public static final int CREATE_BACKUP_AGENT     = 128;
 68         public static final int DESTROY_BACKUP_AGENT    = 129;
 69         public static final int SUICIDE                 = 130;
 70         public static final int REMOVE_PROVIDER         = 131;
 71         public static final int ENABLE_JIT              = 132;
 72         public static final int DISPATCH_PACKAGE_BROADCAST = 133;
 73         public static final int SCHEDULE_CRASH          = 134;
 74         public static final int DUMP_HEAP               = 135;
 75         public static final int DUMP_ACTIVITY           = 136;
 76         public static final int SLEEPING                = 137;
 77         public static final int SET_CORE_SETTINGS       = 138;
 78         public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139;
 79         public static final int TRIM_MEMORY             = 140;
 80         public static final int DUMP_PROVIDER           = 141;
 81         public static final int UNSTABLE_PROVIDER_DIED  = 142;
 82         public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143;
 83         public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144;
 84         public static final int INSTALL_PROVIDER        = 145;
 85         public static final int ON_NEW_ACTIVITY_OPTIONS = 146;
 86         public static final int CANCEL_VISIBLE_BEHIND = 147;
 87         public static final int BACKGROUND_VISIBLE_BEHIND_CHANGED = 148;
 88         public static final int ENTER_ANIMATION_COMPLETE = 149;
 89         String codeToString(int code) {
 90             if (DEBUG_MESSAGES) {
 91                 switch (code) {
 92                     case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
 93                     case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
 94                     case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING";
 95                     case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW";
 96                     case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE";
 97                     case SHOW_WINDOW: return "SHOW_WINDOW";
 98                     case HIDE_WINDOW: return "HIDE_WINDOW";
 99                     case RESUME_ACTIVITY: return "RESUME_ACTIVITY";
100                     case SEND_RESULT: return "SEND_RESULT";
101                     case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY";
102                     case BIND_APPLICATION: return "BIND_APPLICATION";
103                     case EXIT_APPLICATION: return "EXIT_APPLICATION";
104                     case NEW_INTENT: return "NEW_INTENT";
105                     case RECEIVER: return "RECEIVER";
106                     case CREATE_SERVICE: return "CREATE_SERVICE";
107                     case SERVICE_ARGS: return "SERVICE_ARGS";
108                     case STOP_SERVICE: return "STOP_SERVICE";
109                     case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";
110                     case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";
111                     case GC_WHEN_IDLE: return "GC_WHEN_IDLE";
112                     case BIND_SERVICE: return "BIND_SERVICE";
113                     case UNBIND_SERVICE: return "UNBIND_SERVICE";
114                     case DUMP_SERVICE: return "DUMP_SERVICE";
115                     case LOW_MEMORY: return "LOW_MEMORY";
116                     case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED";
117                     case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
118                     case PROFILER_CONTROL: return "PROFILER_CONTROL";
119                     case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";
120                     case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
121                     case SUICIDE: return "SUICIDE";
122                     case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
123                     case ENABLE_JIT: return "ENABLE_JIT";
124                     case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
125                     case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
126                     case DUMP_HEAP: return "DUMP_HEAP";
127                     case DUMP_ACTIVITY: return "DUMP_ACTIVITY";
128                     case SLEEPING: return "SLEEPING";
129                     case SET_CORE_SETTINGS: return "SET_CORE_SETTINGS";
130                     case UPDATE_PACKAGE_COMPATIBILITY_INFO: return "UPDATE_PACKAGE_COMPATIBILITY_INFO";
131                     case TRIM_MEMORY: return "TRIM_MEMORY";
132                     case DUMP_PROVIDER: return "DUMP_PROVIDER";
133                     case UNSTABLE_PROVIDER_DIED: return "UNSTABLE_PROVIDER_DIED";
134                     case REQUEST_ASSIST_CONTEXT_EXTRAS: return "REQUEST_ASSIST_CONTEXT_EXTRAS";
135                     case TRANSLUCENT_CONVERSION_COMPLETE: return "TRANSLUCENT_CONVERSION_COMPLETE";
136                     case INSTALL_PROVIDER: return "INSTALL_PROVIDER";
137                     case ON_NEW_ACTIVITY_OPTIONS: return "ON_NEW_ACTIVITY_OPTIONS";
138                     case CANCEL_VISIBLE_BEHIND: return "CANCEL_VISIBLE_BEHIND";
139                     case BACKGROUND_VISIBLE_BEHIND_CHANGED: return "BACKGROUND_VISIBLE_BEHIND_CHANGED";
140                     case ENTER_ANIMATION_COMPLETE: return "ENTER_ANIMATION_COMPLETE";
141                 }
142             }
143             return Integer.toString(code);
144         }
145         public void handleMessage(Message msg) {
146             if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
147             switch (msg.what) {
148                 case LAUNCH_ACTIVITY: {
149                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
150                     final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
151                     r.packageInfo = getPackageInfoNoCheck(
152                             r.activityInfo.applicationInfo, r.compatInfo);
153                     handleLaunchActivity(r, null);
154                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
155                 } break;
156                 case RELAUNCH_ACTIVITY: {
157                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
158                     ActivityClientRecord r = (ActivityClientRecord)msg.obj;
159                     handleRelaunchActivity(r);
160                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
161                 } break;
162                 case PAUSE_ACTIVITY:
163                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
164                     handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
165                             (msg.arg1&2) != 0);
166                     maybeSnapshot();
167                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
168                     break;
169                 case PAUSE_ACTIVITY_FINISHING:
170                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
171                     handlePauseActivity((IBinder)msg.obj, true, (msg.arg1&1) != 0, msg.arg2,
172                             (msg.arg1&1) != 0);
173                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
174                     break;
175                 case STOP_ACTIVITY_SHOW:
176                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
177                     handleStopActivity((IBinder)msg.obj, true, msg.arg2);
178                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
179                     break;
180                 case STOP_ACTIVITY_HIDE:
181                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
182                     handleStopActivity((IBinder)msg.obj, false, msg.arg2);
183                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
184                     break;
185                 case SHOW_WINDOW:
186                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityShowWindow");
187                     handleWindowVisibility((IBinder)msg.obj, true);
188                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
189                     break;
190                 case HIDE_WINDOW:
191                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityHideWindow");
192                     handleWindowVisibility((IBinder)msg.obj, false);
193                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
194                     break;
195                 case RESUME_ACTIVITY:
196                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
197                     handleResumeActivity((IBinder) msg.obj, true, msg.arg1 != 0, true);
198                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
199                     break;
200                 case SEND_RESULT:
201                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDeliverResult");
202                     handleSendResult((ResultData)msg.obj);
203                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
204                     break;
205                 case DESTROY_ACTIVITY:
206                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy");
207                     handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
208                             msg.arg2, false);
209                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
210                     break;
211                 case BIND_APPLICATION:
212                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
213                     AppBindData data = (AppBindData)msg.obj;
214                     handleBindApplication(data);
215                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
216                     break;
217                 case EXIT_APPLICATION:
218                     if (mInitialApplication != null) {
219                         mInitialApplication.onTerminate();
220                     }
221                     Looper.myLooper().quit();
222                     break;
223                 case NEW_INTENT:
224                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityNewIntent");
225                     handleNewIntent((NewIntentData)msg.obj);
226                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
227                     break;
228                 case RECEIVER:
229                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
230                     handleReceiver((ReceiverData)msg.obj);
231                     maybeSnapshot();
232                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
233                     break;
234                 case CREATE_SERVICE:
235                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
236                     handleCreateService((CreateServiceData)msg.obj);
237                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
238                     break;
239                 case BIND_SERVICE:
240                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
241                     handleBindService((BindServiceData)msg.obj);
242                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
243                     break;
244                 case UNBIND_SERVICE:
245                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind");
246                     handleUnbindService((BindServiceData)msg.obj);
247                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
248                     break;
249                 case SERVICE_ARGS:
250                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStart");
251                     handleServiceArgs((ServiceArgsData)msg.obj);
252                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
253                     break;
254                 case STOP_SERVICE:
255                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop");
256                     handleStopService((IBinder)msg.obj);
257                     maybeSnapshot();
258                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
259                     break;
260                 case CONFIGURATION_CHANGED:
261                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");
262                     mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi;
263                     handleConfigurationChanged((Configuration)msg.obj, null);
264                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
265                     break;
266                 case CLEAN_UP_CONTEXT:
267                     ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
268                     cci.context.performFinalCleanup(cci.who, cci.what);
269                     break;
270                 case GC_WHEN_IDLE:
271                     scheduleGcIdler();
272                     break;
273                 case DUMP_SERVICE:
274                     handleDumpService((DumpComponentInfo)msg.obj);
275                     break;
276                 case LOW_MEMORY:
277                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "lowMemory");
278                     handleLowMemory();
279                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
280                     break;
281                 case ACTIVITY_CONFIGURATION_CHANGED:
282                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityConfigChanged");
283                     handleActivityConfigurationChanged((ActivityConfigChangeData)msg.obj);
284                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
285                     break;
286                 case PROFILER_CONTROL:
287                     handleProfilerControl(msg.arg1 != 0, (ProfilerInfo)msg.obj, msg.arg2);
288                     break;
289                 case CREATE_BACKUP_AGENT:
290                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupCreateAgent");
291                     handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
292                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
293                     break;
294                 case DESTROY_BACKUP_AGENT:
295                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupDestroyAgent");
296                     handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
297                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
298                     break;
299                 case SUICIDE:
300                     Process.killProcess(Process.myPid());
301                     break;
302                 case REMOVE_PROVIDER:
303                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "providerRemove");
304                     completeRemoveProvider((ProviderRefCount)msg.obj);
305                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
306                     break;
307                 case ENABLE_JIT:
308                     ensureJitEnabled();
309                     break;
310                 case DISPATCH_PACKAGE_BROADCAST:
311                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastPackage");
312                     handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
313                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
314                     break;
315                 case SCHEDULE_CRASH:
316                     throw new RemoteServiceException((String)msg.obj);
317                 case DUMP_HEAP:
318                     handleDumpHeap(msg.arg1 != 0, (DumpHeapData)msg.obj);
319                     break;
320                 case DUMP_ACTIVITY:
321                     handleDumpActivity((DumpComponentInfo)msg.obj);
322                     break;
323                 case DUMP_PROVIDER:
324                     handleDumpProvider((DumpComponentInfo)msg.obj);
325                     break;
326                 case SLEEPING:
327                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "sleeping");
328                     handleSleeping((IBinder)msg.obj, msg.arg1 != 0);
329                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
330                     break;
331                 case SET_CORE_SETTINGS:
332                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setCoreSettings");
333                     handleSetCoreSettings((Bundle) msg.obj);
334                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
335                     break;
336                 case UPDATE_PACKAGE_COMPATIBILITY_INFO:
337                     handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj);
338                     break;
339                 case TRIM_MEMORY:
340                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "trimMemory");
341                     handleTrimMemory(msg.arg1);
342                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
343                     break;
344                 case UNSTABLE_PROVIDER_DIED:
345                     handleUnstableProviderDied((IBinder)msg.obj, false);
346                     break;
347                 case REQUEST_ASSIST_CONTEXT_EXTRAS:
348                     handleRequestAssistContextExtras((RequestAssistContextExtras)msg.obj);
349                     break;
350                 case TRANSLUCENT_CONVERSION_COMPLETE:
351                     handleTranslucentConversionComplete((IBinder)msg.obj, msg.arg1 == 1);
352                     break;
353                 case INSTALL_PROVIDER:
354                     handleInstallProvider((ProviderInfo) msg.obj);
355                     break;
356                 case ON_NEW_ACTIVITY_OPTIONS:
357                     Pair<IBinder, ActivityOptions> pair = (Pair<IBinder, ActivityOptions>) msg.obj;
358                     onNewActivityOptions(pair.first, pair.second);
359                     break;
360                 case CANCEL_VISIBLE_BEHIND:
361                     handleCancelVisibleBehind((IBinder) msg.obj);
362                     break;
363                 case BACKGROUND_VISIBLE_BEHIND_CHANGED:
364                     handleOnBackgroundVisibleBehindChanged((IBinder) msg.obj, msg.arg1 > 0);
365                     break;
366                 case ENTER_ANIMATION_COMPLETE:
367                     handleEnterAnimationComplete((IBinder) msg.obj);
368                     break;
369             }
370             if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
371         }
372         private void maybeSnapshot() {
373             if (mBoundApplication != null && SamplingProfilerIntegration.isEnabled()) {
374                 // convert the *private* ActivityThread.PackageInfo to *public* known
375                 // android.content.pm.PackageInfo
376                 String packageName = mBoundApplication.info.mPackageName;
377                 android.content.pm.PackageInfo packageInfo = null;
378                 try {
379                     Context context = getSystemContext();
380                     if(context == null) {
381                         Log.e(TAG, "cannot get a valid context");
382                         return;
383                     }
384                     PackageManager pm = context.getPackageManager();
385                     if(pm == null) {
386                         Log.e(TAG, "cannot get a valid PackageManager");
387                         return;
388                     }
389                     packageInfo = pm.getPackageInfo(
390                             packageName, PackageManager.GET_ACTIVITIES);
391                 } catch (NameNotFoundException e) {
392                     Log.e(TAG, "cannot get package info for " + packageName, e);
393                 }
394                 SamplingProfilerIntegration.writeSnapshot(mBoundApplication.processName, packageInfo);
395             }
396         }
397     }
View Code

 

11.android sdk中都提供了哪些類 扮演著執行緒的角色?

答:主要是asynctask intentservice 以及handlerthread。其中前者的核心是執行緒池,後兩者的實現核心是執行緒。intentservice 講白了就是一個後臺執行緒

只不過這個執行緒扮演了service的角色 讓系統不會輕易的殺死這個執行緒而已。

 

12.使用asynctask有哪些注意事項?

答:asynctask的原始碼分析 我以前寫過 這裡就不多說了,http://www.cnblogs.com/punkisnotdead/p/4469612.html 可以參考。

      主要就是不同版本 asynctask 內部實現不一樣。 特別耗時的任務 我們不要放在asynctask 這裡做。

  使用要點:

      1.asynctask 要在ui執行緒也就是主執行緒建立

  2.execute也要在ui執行緒執行

  3.一個asynctask只能執行一次execute方法。

  4.3.0以後的android版本 asynctask 都是序列執行任務的。(這就是為什麼耗時任務不要在這裡做的原因 你耗時了 其他資源就用不了了) 3.0以前是並行執行的

  你當然可以用executeOnExecutor來並行執行任務。如果用這個方法 你可以考慮做一些耗時任務。

 

13.thread和handlerthread的區別在哪?

答:

 1 //區別主要就在run方法裡,thread的run方法就是執行一個耗時任務
 2 //而hh 在內部建立了訊息佇列。
 3 
 4 @Override
 5     public void run() {
 6         mTid = Process.myTid();
 7         Looper.prepare();
 8         synchronized (this) {
 9             mLooper = Looper.myLooper();
10             notifyAll();
11         }
12         Process.setThreadPriority(mPriority);
13         onLooperPrepared();
14         //這裡開啟訊息迴圈 會在訊息佇列的next方法那邊block住,所以你不用的時候 一定記得quit!
15         Looper.loop();
16         mTid = -1;
17     }
18     
View Code

 

 

14.intentservice的原理?

答:

 1 //intentservice 在onCreate方法裡啟動了一個handlerthread
 2 //注意service的onCreate方法 只在第一次啟動時候才被呼叫
 3 public void onCreate() {
 4         // TODO: It would be nice to have an option to hold a partial wakelock
 5         // during processing, and to have a static startService(Context, Intent)
 6         // method that would launch the service & hand off a wakelock.
 7 
 8         super.onCreate();
 9         HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
10         thread.start();
11 
12         mServiceLooper = thread.getLooper();
13         mServiceHandler = new ServiceHandler(mServiceLooper);
14     }
15 
16 
17 
18 //而service的onStartCommand 是每次啟動都被呼叫的
19     public int onStartCommand(Intent intent, int flags, int startId) {
20         onStart(intent, startId);
21         return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
22     }
23 
24 //所以你看startservice 傳送的intent 被傳送到了這裡
25      @Override
26     public void onStart(Intent intent, int startId) {
27         Message msg = mServiceHandler.obtainMessage();
28         msg.arg1 = startId;
29         msg.obj = intent;
30         mServiceHandler.sendMessage(msg);
31     }
32 
33 //intent傳送到這裡被處理
34      private final class ServiceHandler extends Handler {
35         public ServiceHandler(Looper looper) {
36             super(looper);
37         }
38 
39         @Override
40         public void handleMessage(Message msg) {
41             //處理完我們的intent 就結束了 所以這個intentservice 也是順序執行任務的
42             onHandleIntent((Intent)msg.obj);
43             //stopself方法是立即停止 而我們這是是用的stopself(int startId) 這個方法會等待所有訊息處理完畢以後才停止
44             stopSelf(msg.arg1);
45         }
46     }
47 
48 //這個方法教給子類去實現的。
49      @WorkerThread
50     protected abstract void onHandleIntent(Intent intent);
View Code

 

15.在android中使用執行緒池 有什麼需要注意的地方?

答:其實android中的執行緒池 跟java中的一模一樣。就是通過Executor介面來操作的。

 1 package com.example;
 2 
 3 /**
 4  * Created by Administrator on 2016/2/15.
 5  */
 6 
 7 import java.util.concurrent.BlockingQueue;
 8 import java.util.concurrent.ExecutorService;
 9 import java.util.concurrent.Executors;
10 import java.util.concurrent.TimeUnit;
11 
12 /**
13  * 理解好執行緒池 主要就是理解好核心執行緒這個概念 核心執行緒 的意思 就是永遠不消亡,不存在超時機制,核心執行緒會一直存在與執行緒池之中 閒置狀態也會一直存在。
14  * 非核心執行緒 超時以後 就自動被執行緒池回收了
15  * 所以根據這一點 我們就可以根據我們的業務模型 選擇合適的執行緒池。
16  */
17 public class ThreadExcutorsExample {
18 
19     public static void main(String[] args)
20     {
21         //這種執行緒池只有核心執行緒,這些執行緒永遠不會被回收的。所以這種執行緒池適合 需要快速響應外界請求的 場景。
22         ExecutorService fixedThreadPool= Executors.newFixedThreadPool(4);
23 
24         //這種執行緒池 沒有核心執行緒,全都是非核心執行緒,超時時間為60s 也就是說超過60s 沒有任務進來處理 就自動銷燬.
25         //最大執行緒數就是Intger。Maxvalue 理論上就是可以開啟無線個執行緒。
26         //當沒有任務進來的時候 這個執行緒池 就沒有執行緒了。所以適合執行 大量耗時較少的場景
27         ExecutorService cacheThreadPool=Executors.newCachedThreadPool();
28 
29         //核心執行緒數量固定 非核心執行緒沒有限制, 定時任務什麼的 可以用這個 比較合適
30         ExecutorService scheduledThreadPool=Executors.newScheduledThreadPool(4);
31 
32         //就只有一個核心執行緒,非核心執行緒也沒有。所以這種執行緒池就是順序處理任務的
33         ExecutorService singleThreadPool=Executors.newSingleThreadScheduledExecutor();
34 
35 //  他們內部都是通過ThreadPoolExecutor這個構造方法 來構造對應的執行緒池的。asynctask 不同版本的原始碼 你都可以看看 是怎麼構造的。
36 //  其實都是這個建構函式 傳遞了不同的引數而已。
37 //        public ThreadPoolExecutor(int corePoolSize,
38 //        int maximumPoolSize,
39 //        long keepAliveTime,
40 //        TimeUnit unit,
41 //        BlockingQueue<Runnable> workQueue) {
42 //        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
43 //                Executors.defaultThreadFactory(), defaultHandler);
44     }
45     }
46 }
View Code

 

相關文章