本篇文章為一個 Android WorkerThread的Data透過Handler丟到MainThread中 的範例。
在一個Android Application中,顯示給User使用的UI介面是工作在主線程上 ,其主線程為MainThread,如果當一個工作阻塞在MainThread中超過5秒(onCreat 10秒),系統即發生ANR事件(Application Not Responding)。
例如在MainThread中加入一個 Thread.sleep(5000),系統即發生ANR,因此MainThread主要是用來給User使用的UI線程,如果有一些較繁重的工作、重複性高或演算法(例如一個不斷從Internet不斷抓取資料的工作),則需另外開一個Thread(WorkerThread)專門負責該項工作,除了MainThread以外的Thread都稱WorkerThread。
在一個Application當中,WorkThread無法直接使用TextView、Button等UI控件(progressBar可以),這是因為這些UI控件都是在MainThread當中所生成,因此如果一個WorkerThread想要使用TextView或Button等控件,則需使用Handler,將一個Handler生成在MainThread當中,WorkerThread將資料丟到Handler中後,再將資料顯示在TextView上。以下將示範 點擊Button後,WorkerThread內的Data透過Handler丟到MainThread中的TextView顯示出來:
一開始建立所需使用的 button1、textview1、handler1,
private Button button1;//建立button1物件,點擊按鈕時,執行MyThread Function,讓MyThread透過handler1傳送 字串給textview1
private TextView textview1;//建立textview1物件
private Handler handler1; //建立handler1
在onCreat中將button1與textview1綁定ID,button1的監聽器綁button1listener() function,
將handler1綁Myhandler() function。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1=(Button)findViewById(R.id.btn1ID);
textview1=(TextView)findViewById(R.id.tv1ID);
button1.setOnClickListener(new button1listener());
handler1=new MyHandler(); //handler1綁MyHandler Function
}
建立一個 Button onClickListener的 class,實現 onClickListener,當點擊Button1時,將運行此Function,此Function將建立一個Thread t,其綁到MyThread() function
上,並使用 start()方始使該Thread開始執行。
class button1listener implements View.OnClickListener{ //點擊button1時,建立一個t綁MyThread,並使之開始
@Override
public void onClick(View v) {
Thread t=new MyThread();//建立一個Thread t使用MyThread function
t.start(); //t開始
}
}
建立一個名稱為 MyThread的WorkerThread,其class是繼承 Thread方法。
在MyThread當中,建立一個信息對象msg獲取handler1.obtainMessage(),得到handler1的消息對象後,
便可對msg丟data,如果是 data是int,使用msg.what儲存資料,如果data是string,則使用msg.obj儲存資料。
最後再透過handler1.sendMessage(msg) 方法,將資料丟到消息對列當中。
//WorkerThread
class MyThread extends Thread{ //將字串存到handler1的msg
@Override
public void run(){
try {
Thread.sleep(1*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String s="This is MyThread's string";
//創建一個消息對象,並使用Handler發送該對象
Message msg=handler1.obtainMessage(); //獲取handler1的消息對象
msg.obj= s;//設定消息=s
handler1.sendMessage(msg);//將消息(msg)放在消息對列中
//1.Looper將會從消息對列中取出msg
//2.Looper將會找到與消息對象對應的Handler對象 (此處 msg與handler1對應)
//3.Looper將會調用handler1對象的handlerMessage(Message msg)方法,用於處理消息對象
}
}
建立一個MyHandler,其class繼承Handler方法。 其MyHandler是建立在MainThread當中,因此會不斷地循環偵測Message
其handleMessage內,將消息對列中的msg抓出來並儲存到 obj中,再將obj資料顯示在textview1。
class MyHandler extends Handler{
@Override
public void handleMessage(Message msg){
Object obj=msg.obj;
textview1.setText(obj + "");
System.out.println(obj+"");
}
}
以上為WorkerThread向MainThread丟資料的方法,下一篇則是相反,由MainThread向WorkerThread丟資料。