標籤:android style blog http color java os 檔案
這裡主要講的是Android中線程的概念,自己的線程不能更新UI線程中的視圖。如果把Handler設定在自己的線程中,那麼必須建立一個Looper。至於為什麼在Activity中建立Handler就不用建立一個Looper呢,因為在UI線程初始化時就已經有一個Loop了,所以直接用就行。這裡還需要注意一個先後的問題。發送訊息這個動作必須線上程初始化後,否則出錯。至於線程初始化的時間和start()方法的執行時間無關,start()後表示進入就緒態,但沒確定可以執行。
布局檔案就一個Button和TextView,就不貼出來了。
MainActivity.java
package com.kale.handler;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.view.View;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends Activity { TextView valeTv; // 定義索引值對 private String KEY = "key"; private String VALUE = "value"; // 定義一個自己的線程 class MyThread extends Thread { public Handler mHandler; @Override public void run() { System.out.println("線程開始運行"); Looper.prepare();// 線上程中必須建立一個自己的looper,不能用ui線程中的 mHandler = new Handler() {// 在新線程中建立Handler時必須建立Looper public void handleMessage(Message msg) { if (msg.what == 111) { String str = msg.getData().getString(KEY); // valeTv.setText(str);//不能更新ui Toast.makeText(MainActivity.this, str, 0).show(); } }; }; Looper.loop(); } } private MyThread thread; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); valeTv = (TextView) findViewById(R.id.vale_textView); thread = new MyThread(); // 啟動線程 thread.start(); //sentMsg();//發在這很危險,因為發送訊息的動作可能線上程執行前,這樣就出錯了 } public void buttonListener(View v) { sentMsg();//因為點擊事件肯定線上程開始執行後才進行,所以這裡是正確的 } private void sentMsg() { // 建立訊息 Message msg = new Message(); msg.what = 111; Bundle bundle = new Bundle(); bundle.putString(KEY, VALUE); // 設定資料 msg.setData(bundle); System.out.println("向線程發送訊息");// 這句話必須在“線程開始運行”後列印才表示正確 // 發送訊息,由於線程執行的時間不固定,這句話必須放線上程start後的一段時間才行。這裡放在點擊事件中,確保線程已經開始執行了。 thread.mHandler.sendMessage(msg); }}
Log表示的是正確的先後順序,注意一下。