一.什么是handler
android中 只有主線程才能更新ui,handler通知ui更新 耗時(shí)操作,(文件讀取赛糟,網(wǎng)絡(luò)數(shù)據(jù)獲取 )
Message 傳遞的是消息 MessageQueue 消息隊(duì)列
二.handler的使用方法
1.post(runnable)
post 最終調(diào)用的也是hander方法
public class MainActivity extends BaseActicity {
//hander 綁定的是ui線程
private Handler mHandler = new Handler();
public static void show(Context context) {
context.startActivity(new Intent(context, MainActivity.class));
}
@Override
protected int getContentLayoutId() {
return R.layout.activity_main;
}
@Override
protected void initWidget() {
super.initWidget();
}
@Override
protected void initData() {
super.initData();
//啟動(dòng)線程
DownLoadThread downLoadThread = new DownLoadThread();
downLoadThread.start();
}
class DownLoadThread extends Thread{
@Override
public void run() {
Logger.show("文件","開(kāi)始下載");
try {
Thread.sleep(5000);
Logger.show("文件","下載完成");
Runnable runable = new Runnable() {
@Override
public void run() {
//todo 可以在主線程 更新ui
Logger.show("文件","下載完成");
}
};
//這里 執(zhí)行的結(jié)果是在 UI線程
mHandler.post(runable);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2.sendMessage(message)
public class MainActivity extends BaseActicity {
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case 1:
// 進(jìn)行ui操作
break;
}
}
};
public static void show(Context context) {
context.startActivity(new Intent(context, MainActivity.class));
}
@Override
protected int getContentLayoutId() {
return R.layout.activity_main;
}
@Override
protected void initData() {
super.initData();
DownLoadThread downLoadThread = new DownLoadThread();
downLoadThread.start();
}
class DownLoadThread extends Thread{
@Override
public void run() {
Logger.show("文件","開(kāi)始下載");
try {
Thread.sleep(5000);
Logger.show("文件","下載完成");
Message msg = new Message();
// msg = Message.obtain();
//產(chǎn)生一個(gè)Message對(duì)象男摧,可以new 阁吝,也可以使用Message.obtain()方法声登;兩者都可以涵紊,但是更建議使用obtain方法愚铡,因?yàn)镸essage內(nèi)部維護(hù)了一個(gè)Message池用于Message的復(fù)用蛉签,避免使用new 重新分配內(nèi)存。
msg.what=1;
// msg.arg1
mHandler.sendMessage(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
三. hander 機(jī)制的原理
參考博文 :Android 異步消息處理機(jī)制 讓你深入理解 Looper沥寥、Handler碍舍、Message三者關(guān)系http://blog.csdn.net/lmj623565791/article/details/38377229
Handler 、 Looper 邑雅、Message 這三者都與Android異步消息處理線程相關(guān)的概念
那么什么叫異步消息處理線程呢片橡?
異步消息處理線程啟動(dòng)后會(huì)進(jìn)入一個(gè)無(wú)限的循環(huán)體之中,每循環(huán)一次蒂阱,從其內(nèi)部的消息隊(duì)列中取出一個(gè)消息锻全,然后回調(diào)相應(yīng)的消息處理函數(shù),執(zhí)行完成一個(gè)消息后則繼續(xù)循環(huán)录煤。若消息隊(duì)列為空鳄厌,線程則會(huì)阻塞等待。
其實(shí)Looper負(fù)責(zé)的就是創(chuàng)建一個(gè)MessageQueue妈踊,然后進(jìn)入一個(gè)無(wú)限循環(huán)體不斷從該MessageQueue中讀取消息了嚎,而消息的創(chuàng)建者就是一個(gè)或多個(gè)Handler 。
Handler不僅可以更新UI,你完全可以在一個(gè)子線程中去創(chuàng)建一個(gè)Handler歪泳,然后使用這個(gè)handler實(shí)例在任何其他線程中發(fā)送消息萝勤,最終處理消息的代碼都會(huì)在你創(chuàng)建Handler實(shí)例的線程中運(yùn)行。
mHandler = new Handler(context.getMainLooper()) 運(yùn)行在主線程
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
四.hander引起的內(nèi)存泄漏和解決辦法
創(chuàng)建hander 不是靜態(tài)內(nèi)部類 會(huì)隱匿持有外部activity對(duì)象
解決方法:
- 把hander 定義為靜態(tài)內(nèi)部類
如果需要調(diào)用activity 需要使用弱引用的方式
- mHandler.removeCallbacks(Thread);
public class HandlerActivity extends AppCompatActivity {
private final static int MESSAGECODE = 1 ;
private static Handler handler ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler);
findViewById( R.id.finish ).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
//創(chuàng)建Handler
handler = new MyHandler( this ) ;
//創(chuàng)建線程并且啟動(dòng)線程
new Thread( new MyRunnable() ).start();
}
private static class MyHandler extends Handler {
WeakReference<HandlerActivity> weakReference ;
public MyHandler(HandlerActivity activity ){
weakReference = new WeakReference<HandlerActivity>( activity) ;
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if ( weakReference.get() != null ){
// update android ui
Log.d("mmmmmmmm" , "handler " + msg.what ) ;
}
}
}
private static class MyRunnable implements Runnable {
@Override
public void run() {
handler.sendEmptyMessage( MESSAGECODE ) ;
try {
Thread.sleep( 8000 );
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.sendEmptyMessage( MESSAGECODE ) ;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//如果參數(shù)為null的話呐伞,會(huì)將所有的Callbacks和Messages全部清除掉敌卓。
handler.removeCallbacksAndMessages( null );
}
}