Handler會關聯一個單獨的線程和消息隊列。Handler默認關聯主線程,雖然要提供Runnable參數 ,但默認是直接調用Runnable中的run()方法。也就是默認下會在主線程執行,如果在這里面的操作會有阻塞,界面也會卡住。如果要在其他線程執行,可以使用HandlerThread。
HandlerThread的使用
//Handler handler = new Handler() { //... //} HandlerThread uIhandlerThread = new HandlerThread("update"); uIhandlerThread.start(); //Handler UIhandler = new Handler(uIhandlerThread.getLooper()); Handler uIhandler = new Handler(uIhandlerThread.getLooper(),new Callback() { public boolean handleMessage(Message msg) { Bundle b = msg.getData(); int age = b.getInt("age"); String name = b.getString("name"); System.out.println("age is " + age + ", name is" + name); System.out.println("Handler--->" + Thread.currentThread().getId()); System.out.println("handlerMessage"); return true; } });
當要停止uIhandlerThread執行時用:
if(uIhandlerThread!=null) { pointThread.quit(); }
Handler的使用
目前常使用的有兩種用法,
一種是自定義Handler,在handleMessage進行事件的處理, 這個Message可以是在其他線程中send的,或者在主線程中send。
在線程中發送信息到主進程:
1.定義handler
public class MyHandler extends Handler { @Override public boolean handleMessage(Message msg) { switch (msg.what){ case 1 : .... } } } MyHandler myHandler = new MyHandler();
或者
Handler myHandler = new Handler(new Callback(){ // 參數也可以為(this.getMainLooper(),new Callback(){})不寫則默認為主進程的Looper @Override public boolean handleMessage(Message msg) { // TODO Auto-generated method stub return false; } });
2.新建一個線程
Thread sender = new Thread(){ @Override public void run() { .... myHandler.obtainMessage( inWhat , inA , inB , inToken ); myHandler.sendMessage( inMessage ); //myHandler.sendEmptyMessage( inWhat ); } } sender.start();
在主線程中發信息到handler
直接在主進程,不在線程中mHandler.sendMessage( inMessage );
另一種為post一個線程進去,執行線程。直到線程退出或者是handler被removeCallbacks。
定義一個線程Tread名為sender(不重復了)。
然后執行,myHandler.post(sender);
這樣線程就在handler中執行。如果要停止線程的話:
if(myHandler!=null) { myHandler.removeCallbacks(senderObj); }
也可用一個Runnable來代替Thread
Runnable r = new Runnable() { @Override public void run() { // TODO Auto-generated method stub } }; myHandler.post(r);
以上兩種,是否使用handler的post來啟動,差別在與是否開啟新線程來執行處理。使用post方法時,直接調用Thread或Runnable的run方法,所有處理都在主線程中進行,並沒有開啟定義的Thread或Runnable新的線程!!
==============================================================================================
關於Thread和Runnable的區別
參考網址:http://www.360doc.com/content/10/1219/22/573136_79607619.shtml
Thread和Runnable是實現java多線程的兩種方式,Thread是類,Runnable為接口,建議使用Runnable來實現多線程。
如果讓一個線程實現Runnable接口,那么當調用這個線程的對象開啟多個線程時,可以讓這些線程調用同一個變量;
若這個線程是由繼承Thread類而來,則要通過內部類來實現上述的功能,利用的就是內部類可任意訪問外部類變量這個特性。(精辟!!)
例子程序:
public class ThreadTest { public static void main(String[] args) { MyThread mt=new MyThread(); new Thread(mt).start(); //通過實現Runnable的類的對象來開辟第一個線程 new Thread(mt).start(); //通過實現Runnable的類的對象來開辟第二個線程 new Thread(mt).start(); //通過實現Runnable的類的對象來開辟第三個線程 //由於這三個線程是通過同一個對象mt開辟的,所以run()里方法訪問的是同一個index } }
class MyThread implements Runnable //實現Runnable接口 { int index=0; public void run() { for(;index<=200;) System.out.println(Thread.currentThread().getName()+":"+index++); } }
------------------------------------------------------
public class ThreadTest { public static void main(String[] args) { MyThread mt=new MyThread(); mt.getThread().start(); //通過返回內部類的對象來開辟第一個線程 mt.getThread().start(); //通過返回內部類的對象來開辟第二個線程 mt.getThread().start(); //通過返回內部類的對象來開辟第三個線程 //由於這三個線程是通過同一個匿名對象來開辟的,所以run()里方法訪問的是同一個index } }
class MyThread { int index=0; private class InnerClass extends Thread //定義一個內部類,繼承Thread { public void run() { for(;index<=200;) System.out.println(getName()+":"+index++); } } Thread getThread() //這個函數的作用是返回InnerClass的一個匿名對象 { return new InnerClass(); } }
// 這里有一個問題:如果內部類要訪問一個外部變量或方法,那么這個變量或方法必須定義為final,但為什么這里的變量index不用定義為final就可以被內部類訪問?
=============================================================================================
Thread的使用
線程的定義於執行
Thread sender = new Thread(){ @Override public void run() { .... } } sender.start();
線程的停止
if (sender != null) { //sender.quit(); sender.join(); // 執行完畢當前處理后停止線程 }