1.進程與線程
- 進程:android一般一個程序占有一個進程棺滞,但可以通過給四大組件指定android:process屬性 開啟單獨,一個進程會運行在
- 線程: 在一個應(yīng)用 中耗時操作一般要開啟子線程去操作累盗,也就是說一個進程可以有多個線程狼忱,它們之間是包含關(guān)系扭仁。
- 子進程和父進程有不同的代碼和數(shù)據(jù)空間讼油,而多個線程則共享數(shù)據(jù)空間,每個線程有自己的執(zhí)行堆棧和程序計數(shù)器為其執(zhí)行上下文颤难。
- 進程間相互獨立神年,同一進程的各線程間共享。某進程內(nèi)的線程在其它進程不可見行嗤。
- 進程間通信IPC已日,線程間可以直接讀寫進程數(shù)據(jù)段(如全局變量)來進行通信——需要進程同步和互斥手段的輔助,以保證數(shù)據(jù)的一致性栅屏。
- 線程間通信除了Handler這種外飘千,還有其他幾種方式:管道Pip堂鲜、共享內(nèi)存、通過文件及數(shù)據(jù)庫等
2.通信
我們使用一個Handler進行通信护奈,線程A缔莲、B和C、D之間霉旗,只有一個可以接收消息并處理痴奏,另一個只能夠發(fā)送。
3.消息處理中的幾大角色
圖片引用地址:http://www.reibang.com/p/7657f541c461
andriod提供了Handler和Looper來滿足線程間的通信厌秒。Handler先進先出原則读拆。Looper類用來管理特定線程內(nèi)對象之間的消息交換
Message
- 線程間通信就是在傳遞消息,Message就是消息的載體鸵闪。常用的有四個字段:arg1檐晕,arg2,what蚌讼,obj辟灰。obj可以攜帶Object對象,其余三個可以攜帶整形數(shù)據(jù)篡石。
MessageQueue
- MessageQueue是持有Message(在Looper中派發(fā))的一個鏈表芥喇,Message并不是直接添加到MessageQueue中的,而是通過與Looper相關(guān)聯(lián)的Handler來進行的凰萨。
- 用來存放線程放入的消息,讀取會自動刪除消息乃坤,單鏈表維護,在插入和刪除上有優(yōu)勢沟蔑。在其next()中會無限循環(huán),不斷判斷是否有消息狱杰,有就返回這條消息并移除瘦材。
Looper
- 一個線程可以產(chǎn)生一個Looper對象,由它來管理此線程里的MessageQueue
- Looper創(chuàng)建的時候會創(chuàng)建一個MessageQueue仿畸,調(diào)用loop()方法的時候消息循環(huán)開始食棕,loop()也是一個死循環(huán),會不斷調(diào)用messageQueue的next()错沽,當(dāng)有消息就處理簿晓,否則阻塞在messageQueue的next()中。當(dāng)Looper的quit()被調(diào)用的時候會調(diào)用messageQueue的quit(),此時next()會返回null千埃,然后loop()方法也跟著退出憔儿。
- MessageQueue和Looper是一對一關(guān)系,Handler和Looper是多對一
- 線程是默認沒有Looper的放可,線程需要通過Looper.prepare()谒臼、綁定Handler到Looper對象朝刊、Looper.loop()來建立消息循環(huán);在主線程蜈缤,也就是ActivityThread拾氓,在被創(chuàng)建的時候就會初始化Looper,所以主線程中可以默認使用Handler
Handler
- 在主線程構(gòu)造一個Handler底哥,與Looper溝通咙鞍,以便push新消息到MessageQueue里;
- 接收Looper從MessageQueue取出Handler所送來的消息。然后在其他線程調(diào)用sendMessage(),此時主線程的MessageQueue中會插入一條message趾徽,然后被Looper使用.
- 用于發(fā)送和處理消息的發(fā)送消息续滋,一般使用sendMessage(),還有sendMessage的方法,但最終都是調(diào)用sendMessageAtTime()方法附较,除了sendMessageAtFrontOfQueue()這個方法吃粒。
- 只要在Looper線程(就是實現(xiàn)了Looper的線程)構(gòu)建Handler類,那么這個Handler實例就獲取該Looper線程MessageQueue實例的引用拒课,Handler 在sendMessage()的時候就通過這個引用往消息隊列里插入新消息徐勃。
Thread
- UIthread 通常就是main thread,而Android啟動程序時會替它建立一個MessageQueue,系統(tǒng)的主線程在ActivityThread的main()為入口開啟主線程早像,其中定義了一系列消息類型僻肖,包含四大組件的啟動停止。
ThreadLocal
- ThreadLocal的作用是提供線程內(nèi)的局部變量卢鹦,這種變量在線程的生命周期內(nèi)起作用臀脏,減少同一個線程內(nèi)多個函數(shù)或者組件之間一些公共變量的傳遞的復(fù)雜度。引用 Android關(guān)于ThreadLocal的思考和總結(jié)
4.創(chuàng)建Handler的兩種方式
一個是在主線程中創(chuàng)建
public class TestActivity extends AppCompatActivity {
private static final String TAG = "TestActivity";
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//獲得發(fā)送Message對象冀自,進行UI操作
Log.e(TAG,"------------> msg.what = " + msg.what);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
initThread();
}
private void initThread() {
//開啟線程處理耗時操作
new Thread(new Runnable() {
@Override
public void run() {
SystemClock.sleep(2000);
//通過Handler發(fā)送消息切換回主線程(mHandler所在的線程)
mHandler.sendEmptyMessage(0);
}
}).start();
}
- 一個是在普通工作線程中創(chuàng)建
public class TestActivity extends AppCompatActivity {
private static final String TAG = "TestActivity";
//主線程的Handler
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//獲得發(fā)送Message對象揉稚,進行UI操作
Log.e(TAG,"------------> msg.what = " + msg.what);
}
};
//子線程中的Handler
private Handler mHandlerThread = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
initThread();
}
private void initThread() {
//開啟線程處理耗時的操作
new Thread(new Runnable() {
@Override
public void run() {
SystemClock.sleep(2000);
//通過Handler發(fā)送消息切換回主線程(mHandler所在的線程)
mHandler.sendEmptyMessage(0);
//調(diào)用Looper.prepare()方法
Looper.prepare();
mHandlerThread = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.e("sub thread","---------> msg.what = " + msg.what);
}
};
mHandlerThread.sendEmptyMessage(1);
//調(diào)用Looper.loop()方法
Looper.loop();
}
}).start();
}
}
- 當(dāng)Looper.prepare()執(zhí)行之后,普通的工作線程就變成了Looper線程熬粗,該線程就可以接收并處理消息
- 而Looper.loop()方法就是進入一個無限循環(huán)搀玖,不斷從MessageQueue中獲取消息,當(dāng)沒有消息時就阻塞在那里
- Handler 對象在哪個線程下構(gòu)建(構(gòu)造函數(shù)在哪個線程下調(diào)用)驻呐,那么Handler 就會持有該線程的Looper引用和消息隊列的引用灌诅。這個Handler對象可在任意其他線程給該線程的消息隊列添加消息,說明Handler的handlerMessage 也在該線程執(zhí)行的含末。如果該線程不是Looper線程猜拾,在這個線程new Handler 就會報錯!