### **Android中線程模型**
[進程線程](http://note.youdao.com/noteshare?id=de140840a1da668b7f2f7f3facb34620)
[Android多線程的四種方式](https://www.jianshu.com/p/2b634a7c49ec)
[理解Android線程創建流程](http://www.hmoore.net/alex_wsc/androidsystem/483949)
[ActivityThread and ApplicationThread](https://www.2cto.com/kf/201312/269075.html)
[Google官網介紹DDMS](https://developer.android.com/studio/profile/monitor.html)
**所有Android 應用的線程都對應一個Linux 線程**,虛擬機因而可以更多地依賴操作系統的線程調度和管理機制。不同的應用在不同的進程空間里運行,加之對不同來源的應用都使用不同的Linux用戶來運行,可以最大限度地保護應用的安全和獨立運行。
**Android線程,一般地就是指Android虛擬機線程**,而虛擬機線程是通過系統調用而創建的Linux線程。純粹的Linux線程與虛擬機線程的區別在于虛擬機線程具有運行Java代碼的runtime. **除了虛擬機線程,還有Native線程和其他線程(可以從DDMS工具查看某一進程中的所有線程)**,對于Native線程又分為是否具有訪問Java代碼的兩類線程。
#### **使用DDMS工具查看APP中進程中的線程**
如何更好地使用DDMS工具可參考以下文章
[Android Studio中怎么使用DDMS工具?](https://www.cnblogs.com/gaobig/p/5029381.html)
[Android的DDMS中的Threads的各個字段的含義](http://blog.csdn.net/candyliuxj/article/details/7430056)
[Android開發調試必備 - 使用DDMS](http://blog.csdn.net/stzy00/article/details/46554529)
>[info] 如何驗證一個進程中的線程數目和種類?
> 可以通過IDE編譯工具(eclipse或者AS)安裝一個APP到模擬器或真機,打開DDMS工具,選擇Thread菜單欄,可以看到當前進程中的線程種類和數目
**注意:下面查看的線程信息,是system_process進程中的信息,還有其他進程中信息,可以自行查看。**
運行AndroidDemo,
**MainActivity.java**
~~~
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
~~~
**activity_main.xml**
~~~
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.wsc.androiddemo.MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
</RelativeLayout>
~~~
打開DDMS,選擇**system_process**,查看系統進程中的線程信息。
如下圖所示:
:-: 
圖1:DDMS分析App線程
:-: 
圖2 :主線程的信息

圖3:android.bg線程中的信息

圖4:ActivityManager線程中的信息
類似圖4中ActivityManager線程的信息的線程還有以下system_process中的線程信息
* android.fg
* android.ui
* android.io
* android.display
* PowerManagerService
* PackageManager
* PackageInstaller
* MountService
* WifiStateMachine
* NetworkStats
* NetworkPolicy
* Wifi2pService
* WifiService
* ConnectivityServiceThread
* NsdService
* ranker
* backup
* WifiWatchdogStateMachine
* WifiManager
* WifiScanningSerice
* WifiRttService
* NetWorkTimeUpdateService
* NetWorkMonitorNetWorkAgentInfo
* DhcpStateMachine
從上面圖4以及類似的24個線程的信息來看,除了主線程,一創建就會調用Looper類和Message Queue類的方法外,其他的線程(圖4以及類似的24個線程,以及其他的線程)也會調用,**能否得出這些線程一誕生就有一個Looper類的對象和一個MQ(Message Queue)數據結構?這還有待驗證**。
查看當前activity所在的進程中的線程的信息,如下圖5所示
:-: 
圖5:App所在進程的線程信息
**結論**:
1. 從上面系統進程和APP進程中線程信息來看,主線程和其他的一些線程的生命周期和它們所在的進程有關,進程被kill殺掉,那么這些線程也就不存在了;在主線程中創建的子線程的生命周期開始于start()方法,終止于run()函數運行結束。 守護線程的生命周期還和JVM有關系,當別的線程都dead時,JVM會kill掉所有守護線程然后退出。
2. 實驗:在APP主線程創建一個子線程,主線程創建一個handler,用于更新UI;在子線程有一個點擊事件,效果是更改主線程中UI的TextView文本內容改變,結果我們在DDMS中APP所在的進程中,沒有看到這個子線程的創建和消失。
**每一個進程在誕生時,都會誕生一個主線程(Main Thread),以及誕生一個Looper類的對象和一個MQ(Message Queue)數據結構**。每當主線程作完事情,就會去執行Looper類。此時,不斷地觀察MQ的動態。如下圖:
**不同進程的地址空間是獨立的**
:-: 
圖6:獨立的進程空間
>[info] **備注**:然而,主線程創建一個子線程時,在預設情形下,子線程并不具有自己的Looper對象和MQ。由于沒有Looper對象,就沒有信息回圈(Message Loop),一旦工作完畢了,此子線程就結束了。
> 既然沒有Looper對象也沒有MQ,也就不能接受外來的Message對象了。則別的線程就無法透過MQ來傳遞信息給它了。
那么,如果別的線程(如主線程)需要與子線程通訊時(這里的意思是主線程傳遞消息 通過handler.sendMessage給子線程),該如何呢? 答案是:替它誕生一個Looper對象和一個MQ就行了。
> 主線程被創建的時候就會默認初始化Looper,因此在主線程中默認可以使用handler,不用手動創建Looper
#### **Android 的單線程模型**
當第一次啟動一個程序時, **Android 會同時啟動一個對應的主線程(Main Thread)**。**主線程主要負責處理與UI 相關的事件**,如用戶的按鍵事件,用戶接觸、屏幕的事件以及屏幕繪圖事件,并把相關的事件分發到對應的組件進行處理,所以**主線程通常又被叫作UI 線程**。
>[warning] **注意**:
> * ActivityThread,不是主線程,只是運行在主線程的一個對象,從[ActivityThread.java源碼](https://www.androidos.net.cn/android/6.0.1_r16/xref/frameworks/base/core/java/android/app/ActivityThread.java)來說,它只是一個final類。
> * ApplicationThread是ActivityThread的私有內部類,也是一個Binder對象。
* * * * *
* * * * *
**備注**:主線程中會構造這兩個類的對象。但是**他們不是線程**,你看看繼承關系就可以知道**ApplicationThread是binder, ActivityThread是一個final類也不是真正的線程**。
如果你用ddms查看某一個進程的所有線程,你會發現它只有一個main thread,當然它可能還有binder thread, jdwp, signal catcher等。
?
一個應用程序對應一個ActivityThread實例,應用程序由activityThread打開消息循環, 同時,一個應用程序也對應一個**ApplicationThread對象**,此對象**是ActivityThread 與 ActivityManagerService連接的橋梁**。
應該不是一個應用程序對應一個ActivityThread實例,而是一個進程對應一個ActivityThread實例,這個進程里面所有的activity對應這一個ActivityThread實例,你可以看看ActivityThread類包含了mActivities。
* * * * *
* * * * *
在開發Android 應用程序時必須遵守單線程模型的原則: **Android UI 操作并不是線程安全的, 并且這些操作必須在UI 線程中執行。**
如果在非UI 線程中直接操作Ul 線程,會拋出異常。
工作線程-----要保證應用 UI 的響應能力,關鍵是不能阻塞 UI 線程。如果執行的操作不能很快完成,則應確保它們在單獨的線程(“后臺”或“工作”線程)中運行。
Android 的單線程模式必須遵守兩條規則:
* 不要阻塞 UI 線程
* 不要在 UI 線程之外訪問 Android UI 工具包
由于UI 線程負責事件的監昕和繪圖處理,因此**必須保證UI 線程能夠隨時響應用戶的需求**,UI 線程里的操作應該像中斷事件那樣短小,費時的操作(如網絡連接)需要另開線程, 否則,如果UI 線程超過5 s 沒有響應用戶請求, 會彈出對話框提醒用戶終止應用程序。
如果在新開的線程中需要對Ul 線程進行設定,就可能違反單線程模型,因此**Android 采用一種復雜的Message Queue 機制保證線程間的通信。**
#### **解析異步消息處理機制**
下圖就是異步消息處理機制流程示意圖

圖7:異步消息處理機制流程示意圖
>[info] **備注**:上圖是Handler消息機制的處理流程,適用于所有的傳遞消息過程:工作線程傳遞消息給主線程,可以是主線程傳遞給工作線程,也可以是各個工作線程之間傳遞消息,還可以是主線程內部傳遞消息。
Android 中的異步消息處理主要由4 個部分組成: Message 、Handler 、MessageQueue 和Looper。
* **Message**
Message 是在線程之間傳遞的消息,它可以在內部攜帶少量的信息,用于在不同線程之間交換數據。
* **Handler**
Handler 顧名思義也就是處理者的意思,它主要是用于發送和處理消息的。發送消息一般是使用Handler 的sendMessage ()方法,而發出的消息經過一系列地輾轉處理后,最終會傳遞到Handler 的handleMessage ()方法中。
* **MessageQueue**
MessageQqeue 是消息隊列的意思,它主要用于存放所有通過Handler 發送的消息。這部分消息會一直存在于消息隊列中,等待被處理。每個線程中只會有一個MessageQueue 對象。
* **Looper**
Looper 是每個線程中的MessageQueue 的管家,調用Looper 的loop ()方法后,就會進入到一個無限循環當中,然后每當發現MessageQueue 中存在一條消息,就會將它取出,并傳遞到Handler 的handleMessage ()方法中。每個線程中也只會有一個Looper 對象。
**子線程傳遞消息給UI線程(主線程)的整體流程如下**:
首先需要在主線程當中創建一個Handler 對象,并重寫handleMessage ()方法。然后當子線程中需要進行UI 操作時,就創建一個Message 對象,并通過Handler 將這條消息發送出去。之后這條消息會被添加到MessageQueue 的隊列中等待被處理,而Looper 則會一直嘗試從MessageQueue 中取出待處理消息,最后分發回Handler 的handleMessage ()方法中。由于Handler 是在主線程中創建的,所以此時handleMessage ()方法中的代碼也會在主線程中運行,于是我們在這里就可以安心地進行UI 操作了。
示例代碼如下所示:
~~~
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
public static final int UPDATE_TEXT = 1;
private TextView text;
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_TEXT:
// 在這里可以進行UI操作
text.setText("Nice to meet you");
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.text);
Button changeText = (Button) findViewById(R.id.change_text);
changeText.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.change_text:
new Thread(new Runnable() {
@Override
public void run() {
Message message = new Message();
message.what = UPDATE_TEXT;
handler.sendMessage(message); // 將Message對象發送出去
}
}).start();
break;
default:
break;
}
}
}
~~~
#### **AsyncTask**
不過為了更加方便我們在子線程中對UI 進行操作, Android 還提供了另外一些好用的工具,比如AsyncTask。借助AsyncTask,即使你對異步消息處理機制完全不了解,也可以十分簡單地從子線程切換到主線程。當然, AsyncTask 背后的實現原理也是基于異步消息處理機制的,只是Android 幫我們做了很好的封裝而已。
AsyncTask 允許對用戶界面執行異步操作。它會先阻塞工作線程中的操作,然后在 UI 線程中發布結果,而無需您親自處理線程和處理程序。要使用它,必須**創建 AsyncTask 子類并實現 doInBackground() 回調方法**,該方法將在后臺線程池中運行。要**更新 UI,必須實現 onPostExecute() 以傳遞doInBackground() 返回的結果并在 UI 線程中運行**,這樣,您即可安全更新 UI。稍后,您可以**通過從 UI 線程調用 execute() 來運行任務**。
**AsyncTask 是一個抽象類**,所以如果我們想使用它,就**必須要創建一個子類去繼承它**。在繼承時我們可以為AsyncTask 類指定3個泛型參數,這3個參數的用途如下。
* Params:在執行AsyncTask 時需要傳入的參數,可用于在后臺任務中使用。
* Progress:后臺任務執行時,如果需要在界面上顯示當前的進度,則使用這里指定的泛型作為進度單位。
* Result:當任務執行完畢后,如果需要對結果進行返回,則使用這里指定的泛型作為返回值類型。
目前我們自定義的DownloadTask 還是一個空任務,并不能進行任何實際的操作,我們還需要去重寫AsyncTask 中的幾個方法才能完成對任務的定制。經常需要去重寫的方法有以下4 個。
* onPreExecute()
* doInBackground(Params ... )
* onProgressUpdate(Progress ... )
* onPostExecute(Result)
AsyncTask 參考文檔:
* 可以使用泛型指定參數類型、進度值和任務最終值
* 方法 **doInBackground() 會在工作線程(非UI線程)上自動執行**
* **onPreExecute()、onPostExecute() 和 onProgressUpdate() 均在 UI 線程中調用**
* doInBackground() 返回的值將發送到 onPostExecute()
* 您可以隨時在 doInBackground() 中調用publishProgress(),以在 UI 線程中執行 onProgressUpdate()
* 您可以隨時取消任何線程中的任務
#### **Android多線程**
關于Android多線程的知識點補充:
當我們啟動一個App的時候,Android系統會啟動一個Linux Process,該Process包含一個Thread,稱為UI Thread或Main Thread。通常一個應用的所有組件都運行在這一個Process中,當然,你可以通過修改四大組件在Manifest.xml中的代碼塊(`<activity><service><provider><receiver>`)中的**android:process**屬性指定其運行在不同的process中。當一個組件在啟動的時候,如果該process已經存在了,那么該組件就直接通過這個process被啟動起來,并且運行在這個process的UI Thread中。
UI Thread中運行著許多重要的邏輯,如系統事件處理,用戶輸入事件處理,UI繪制,Service,Alarm等
:-: 
圖8:UI Thread包含的邏輯
我們編寫的代碼則是穿插在這些邏輯中間,比如對用戶觸摸事件的檢測和響應,對用戶輸入的處理,自定義View的繪制等。如果我們插入的代碼比價耗時,如網絡請求或數據庫讀取,就會阻塞UI線程其他邏輯的執行,從而導致界面卡頓。如果卡頓時間超過5秒,系統就會報ANR錯誤。所以,如果要執行耗時的操作,我們需要另起線程執行。
在新線程執行完耗時的邏輯后,往往需要將結果反饋給界面,進行UI更新。Android的UI toolkit(UI 工具包)不是線程安全的,不能在非UI線程進行UI的更新,所有對界面的更新必須在UI線程進行。
Android UI 工具包組件:來自 android.widget 和 android.view 軟件包的組件。
Android提供了四種常用的操作多線程的方式,分別是:
1. Handler+Thread
2. AsyncTask
3. ThreadPoolExecutor
4. IntentService
##### **Handler+Thread**
Android主線程包含一個消息隊列(MessageQueue),該消息隊列里面可以存入一系列的Message或Runnable對象。通過一個Handler你可以往這個消息隊列發送Message或者Runnable對象,并且處理這些對象。每次你新創建一個Handle對象,它會綁定于創建它的線程(也就是UI線程)以及該線程的消息隊列,從這時起,這個handler就會開始把Message或Runnable對象傳遞到消息隊列中,并在它們出隊列的時候執行它們。
:-: 
圖9 :Handler Thread原理圖
Handler可以把一個Message對象或者Runnable對象壓入到消息隊列中,進而在UI線程中獲取Message或者執行Runnable對象,Handler把壓入消息隊列有兩類方式,Post和sendMessage:
**Post方式**:
Post允許把一個Runnable對象入隊到消息隊列中。它的方法有:
~~~
post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable,long)
~~~
對于Handler的Post方式來說,它會傳遞一個Runnable對象到消息隊列中,在這個Runnable對象中,重寫run()方法。一般在這個run()方法中寫入需要在UI線程上的操作。
:-: 
圖10:handler post用法
**sendMessage**:
sendMessage允許把一個包含消息數據的Message對象壓入到消息隊列中。它的方法有:
~~~
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)
~~~
Handler如果使用sendMessage的方式把消息入隊到消息隊列中,需要傳遞一個Message對象,而在Handler中,需要重寫handleMessage()方法,用于獲取工作線程傳遞過來的消息,此方法運行在UI線程上。Message是一個final類,所以不可被繼承。
:-: 
圖11:handler定義
:-: 
圖12:handler sendMessage用法
**優缺點**
1. Handler用法簡單明了,可以將多個異步任務更新UI的代碼放在一起,清晰明了
2. 處理單個異步任務代碼略顯多
**適用范圍**
1. 多個異步任務的更新UI
##### **AsyncTask**
[AsyncTask](https://www.androidos.net.cn/android/6.0.1_r16/xref/frameworks/base/core/java/android/os/AsyncTask.java)是android提供的輕量級的異步類,可以直接繼承AsyncTask,在類中實現異步操作,并提供接口反饋當前異步執行的程度(可以通過接口實現UI進度更新),最后反饋執行的結果給UI主線程。
AsyncTask通過一個阻塞隊列`BlockingQuery<Runnable>`存儲待執行的任務,利用靜態線程池THREAD_POOL_EXECUTOR提供一定數量的線程,默認128個。在Android 3.0以前,默認采取的是并行任務執行器,3.0以后改成了默認采用串行任務執行器,通過靜態串行任務執行器SERIAL_EXECUTOR控制任務串行執行,循環取出任務交給THREAD_POOL_EXECUTOR中的線程執行,執行完一個,再執行下一個。
~~~
class DownloadTask extends AsyncTask<Integer, Integer, String>{
// AsyncTask<Params, Progress, Result>
//后面尖括號內分別是參數(例子里是線程休息時間),進度(publishProgress用到),返回值類型
@Override
protected void onPreExecute() {
//第一個執行方法
super.onPreExecute();
}
@Override
protected String doInBackground(Integer... params) {
//第二個執行方法,onPreExecute()執行完后執行
for(int i=0;i<=100;i++){
publishProgress(i);
try {
Thread.sleep(params[0]);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "執行完畢";
}
@Override
protected void onProgressUpdate(Integer... progress) {
//這個函數在doInBackground調用publishProgress時觸發,雖然調用時只有一個參數
//但是這里取到的是一個數組,所以要用progesss[0]來取值
//第n個參數就用progress[n]來取值
tv.setText(progress[0]+"%");
super.onProgressUpdate(progress);
}
@Override
protected void onPostExecute(String result) {
//doInBackground返回時觸發,換句話說,就是doInBackground執行完后觸發
//這里的result就是上面doInBackground執行后的返回值,所以這里是"執行完畢"
setTitle(result);
super.onPostExecute(result);
}
}
~~~
**優缺點**
1. 處理單個異步任務簡單,可以獲取到異步任務的進度
2. 可以通過cancel方法取消還沒執行完的AsyncTask
3. 處理多個異步任務代碼顯得較多
**適用范圍**
1. 單個異步任務的處理
##### **ThreadPoolExecutor**
ThreadPoolExecutor提供了一組線程池,可以管理多個線程并行執行。這樣一方面減少了每個并行任務獨自建立線程的開銷,另一方面可以管理多個并發線程的公共資源,從而提高了多線程的效率。所以ThreadPoolExecutor比較適合一組任務的執行。Executors利用工廠模式對ThreadPoolExecutor進行了封裝,使用起來更加方便。
:-: 
圖13:ThreadPoolExecutor
Executors提供了四種創建ExecutorService的方法,他們的使用場景如下:
1. Executors.newFixedThreadPool()
創建一個定長的線程池,每提交一個任務就創建一個線程,直到達到池的最大長度,這時線程池會保持長度不再變化
2. Executors.newCachedThreadPool()
創建一個可緩存的線程池,如果當前線程池的長度超過了處理的需要時,它可以靈活的回收空閑的線程,當需要增加時,
它可以靈活的添加新的線程,而不會對池的長度作任何限制
3. Executors.newScheduledThreadPool()
創建一個定長的線程池,而且支持定時的以及周期性的任務執行,類似于Timer
4. Executors.newSingleThreadExecutor()
創建一個單線程化的executor,它只創建唯一的worker線程來執行任務
**適用范圍**
1. 批處理任務
##### **IntentService**
[IntentService](https://www.androidos.net.cn/android/6.0.1_r16/xref/frameworks/base/core/java/android/app/IntentService.java)繼承自Service,是一個抽象類,是一個經過包裝的輕量級的Service,用來接收并處理通過Intent傳遞的異步請求。客戶端通過調用startService(Intent)啟動一個IntentService,利用一個work線程依次處理順序過來的請求,處理完成后自動結束Service。
特點
1. 一個可以處理異步任務的簡單Service
它使用工作線程逐一處理所有啟動請求。如果您不要求服務同時處理多個請求,這是最好的選擇。 您只需實onHandleIntent() 方法即可,該方法會接收每個啟動請求的 Intent,使您能夠執行后臺工作。
擴展 IntentService 類(IntentService 類是一個抽象類,所以需要實現它的子類)特點
* 1、不需要開啟線程,
* 2、不需要關閉服務,它自己關閉
* 3、單線程下載
由于大多數啟動服務都不必同時處理多個請求(實際上,這種多線程情況可能很危險),因此使用 IntentService 類實現服務也許是最好的選擇。
IntentService 執行以下操作:
* 創建默認的工作線程,用于在應用的主線程外執行傳遞給 onStartCommand() 的所有 Intent。
* 創建工作隊列,用于將一個 Intent 逐一傳遞給 onHandleIntent() 實現,這樣您就永遠不必擔心多線程問題。
* 在處理完所有啟動請求后停止服務,因此您永遠不必調用 stopSelf()。
* 提供 onBind() 的默認實現(返回 null)。
* 提供 onStartCommand() 的默認實現,可將 Intent 依次發送到工作隊列和 onHandleIntent() 實現。
* 綜上所述,您只需實現 onHandleIntent() 來完成客戶端提供的工作即可。(不過,您還需要為服務提供小型構造函數。)
示例:
~~~
public class HelloIntentService extends IntentService {
/**
* A constructor is required, and must call the super IntentService(String)
* constructor with a name for the worker thread.
*/
public HelloIntentService() {
super("HelloIntentService");
}
/**
* The IntentService calls this method from the default worker thread with
* the intent that started the service. When this method returns, IntentService
* stops the service, as appropriate.
*/
@Override
protected void onHandleIntent(Intent intent) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
}
}
~~~
只需要一個構造函數和一個 onHandleIntent() 實現即可;不需要開線程。
如果您決定還重寫其他回調方法(如 onCreate()、onStartCommand() 或 onDestroy()),請確保調用超類實現(return super.onStartCommand(intent,flags,startId);),以便 IntentService 能夠妥善處理工作線程的生命周期。
例如,onStartCommand() 必須返回默認實現-----return super.onStartCommand(intent,flags,startId);(即,如何將 Intent 傳遞給 onHandleIntent()):
~~~
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent,flags,startId);
}
~~~
除 onHandleIntent() 之外,您無需從中調用超類的唯一方法就是 onBind()(僅當服務允許綁定時,才需要實現該方法)。
IntentService 可用于**執行后臺耗時的任務**,當任務執行后它會自動停止, 同時由于IntentService 是服務的原因,這導致它的優先級比單純的線程要高很多,所以IntentService 比較**適合執行一些高優先級的后臺任務**,因為它**優先級高不容易被系統殺死。**
在實現上, IntentService 封裝了HandlerThread 和Handler,這一點可以從它的onCreate方法中看出來,
- 前言
- Android系統的體系結構
- Dalvik VM 和 JVM 的比較
- Android 打包應用程序并安裝的過程
- Android ADB工具
- Android應用開發
- Android UI相關知識總結
- Android 中window 、view、 Activity的關系
- Android應用界面
- Android中的drawable和bitmap
- AndroidUI組件adapterView及其子類和Adapter的關系
- Android四大組件
- Android 數據存儲
- SharedPreference
- Android應用的資源
- 數組資源
- 使用Drawable資源
- Material Design
- Android 進程和線程
- 進程
- 線程
- Android Application類的介紹
- 意圖(Intent)
- Intent 和 Intent 過濾器(Google官網介紹)
- Android中關于任務棧的總結
- 任務和返回棧(官網譯文)
- 總結
- Android應用安全現狀與解決方案
- Android 安全開發
- HTTPS
- 安卓 代碼混淆與打包
- 動態注入技術(hook技術)
- 一、什么是hook技術
- 二、常用的Hook 工具
- Xposed源碼剖析——概述
- Xposed源碼剖析——app_process作用詳解
- Xposed源碼剖析——Xposed初始化
- Xposed源碼剖析——hook具體實現
- 無需Root也能Hook?——Depoxsed框架演示
- 三、HookAndroid應用
- 四、Hook原生應用程序
- 五、Hook 檢測/修復
- Android 應用的逆向與加固保護技術
- OpenCV在Android中的開發
- Android高級開發進階
- 高級UI
- UI繪制流程及原理
- Android新布局ConstraintLayout約束布局
- 關鍵幀動畫
- 幀動畫共享元素變換
- Android異步消息處理機制完全解析,帶你從源碼的角度徹底理解
- Android中為什么主線程不會因為Looper.loop()里的死循環卡死?
- 為什么 Android 要采用 Binder 作為 IPC 機制?
- JVM 中一個線程的 Java 棧和寄存器中分別放的是什么?
- Android源碼的Binder權限是如何控制?
- 如何詳解 Activity 的生命周期?
- 為什么Android的Handler采用管道而不使用Binder?
- ThreadLocal,你真的懂了嗎?
- Android屏幕刷新機制