5 Handler与子线程
5-1?自定義與線程相關(guān)的Handler?
1.在線程中通過Looper.prepare()方法創(chuàng)建一個(gè)與線程相關(guān)的Looper對(duì)象;
2.?在線程中通過Handler的new關(guān)鍵字,創(chuàng)建一個(gè)Handler對(duì)象,這個(gè)對(duì)象在創(chuàng)建的時(shí)候會(huì)關(guān)聯(lián)上1中創(chuàng)建的Looper對(duì)象
3.?調(diào)用Looper對(duì)象的loop()方法去輪詢它的MessageQueue
4.?通過其他的線程拿到這個(gè)線程的Handler對(duì)象之后調(diào)用sendMessage()之后,在這個(gè)線程中就可以進(jìn)行Message的處理了。
我們一般是在主線程中創(chuàng)建Handler對(duì)象,在主線程中處理Message,在子線程中調(diào)用這個(gè)Handler對(duì)象的sendMessage()來發(fā)送message。所以Handler是在哪個(gè)線程創(chuàng)建就有哪個(gè)線程處理Message和輪詢,而由別的線程負(fù)責(zé)給這個(gè)Handler發(fā)送Message。
1.注意:在主線程中創(chuàng)建的Handler的handleMessage()方法不要寫耗時(shí)的操作,否則會(huì)導(dǎo)致UI卡死,因?yàn)檫@個(gè)handleMessage()方法是在UI線程中調(diào)用的。
package com.example.yzx; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.widget.TextView;public class SecondActivity extends Activity {private Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {System.out.println("UI---------" + Thread.currentThread());};};class MyThread extends Thread {public Handler handler;@Overridepublic void run() {// TODO Auto-generated method stub Looper.prepare();handler = new Handler() {@Overridepublic void handleMessage(Message msg) {// TODO Auto-generated method stubSystem.out.println("currentThead:" + Thread.currentThread());}};Looper.loop();}}private MyThread thread;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);TextView textView = new TextView(this);textView.setText("hellow Handler");setContentView(textView);thread = new MyThread();thread.start();try {Thread.sleep(500);} catch (InterruptedException e) {// TODO Auto-generated catch block e.printStackTrace();}thread.handler.sendEmptyMessage(1);handler.sendEmptyMessage(1);} }?
5-2?HanlderThread是什么?(11:51)
HandlerThread避免多線程導(dǎo)致空指針問題。
handlerthread?默認(rèn)【創(chuàng)建一個(gè)looper然后和一handler關(guān)聯(lián),那么所有的handleMessage方法是在一個(gè)子線程中進(jìn)行,可以用handlerthread模擬一個(gè)異步任務(wù),將主線程的任務(wù)發(fā)送個(gè)子線程,處理一些比較耗時(shí)操作
-----------------------------------------------------------------------------------------
1.一個(gè)Handler的創(chuàng)建它就會(huì)被綁定到這個(gè)線程的消息隊(duì)列中,如果是在主線程創(chuàng)建的,那就不需要寫代碼來創(chuàng)建消息隊(duì)列了,默認(rèn)的消息隊(duì)列會(huì)在主線程被創(chuàng)建。但是如果是在子線程的話,就必須在創(chuàng)建Handler之前先初始化線程的消息隊(duì)列
2.HandlerThread繼承于Thread,所以它本質(zhì)就是個(gè)Thread。與普通Thread的差別就在于,它有個(gè)Looper成員變量。這個(gè)Looper其實(shí)就是對(duì)消息隊(duì)列以及隊(duì)列處理邏輯的封裝,簡(jiǎn)單說就是?消息隊(duì)列+消息循環(huán)。
在其run()方法中,調(diào)用Looper.myLooper()獲得一個(gè)looper對(duì)象。
synchronized?(this)?{
mLooper?=?Looper.myLooper();
notifyAll();
在創(chuàng)建handler時(shí)使用getLooper()方法,其實(shí)現(xiàn)其實(shí)是一直等待looper對(duì)象的獲得。
while?(isAlive()?&&?mLooper?==?null)?{
try?{
wait();
}
}
3.Handler在創(chuàng)建的時(shí)候可以指定Looper,這樣通過Handler的sendMessage()方法發(fā)送出去的消息就會(huì)添加到指定Looper里面的MessageQueue里面去。在不指定Looper的情況下,Handler綁定的是創(chuàng)建它的線程的Looper。如果這個(gè)線程的Looper不存在,程序?qū)伋?#34;Can't?create?handler?inside?thread?that?has?not?called?Looper.prepare()"。
這個(gè)時(shí)候我們就需要使用HandlerThread這個(gè)類來創(chuàng)建這個(gè)Looper了,這樣消息的處理就在新創(chuàng)建的HandlerThread中進(jìn)行。(如圖)
mThread?=?new?HandlerThread("Handler?Thread");
mHandler?=?new?Handler(mThread.getLooper()){
public?void?handleMessage(android.os.Message?msg)?{
...?};
};
兩個(gè)線程切換的過程中,looper沒有創(chuàng)建?會(huì)拋出控制異常
handlerThread用來避免這個(gè)異常
轉(zhuǎn)載于:https://www.cnblogs.com/crazyzx/articles/5477398.html
總結(jié)
以上是生活随笔為你收集整理的5 Handler与子线程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: javaScript初学笔记(二)
- 下一篇: iOS中NSLog输出格式大全