在android平臺下,進行多線程編程時,經常需要在主線程之外的一個單獨的線程中進行某些處理,然後更新用戶界面顯示。但是,在主線線程之外的線程中直接更新頁面顯示的問題是:系統會報這個異常,android.view.viewroot$calledfromwrongthreadexception: only the original thread that created a view hierarchy can touch its views. (只有原始創建這個視圖層次(view hierachy)的線程才能修改它的視圖(view)。)。
也就是說必須在程序的主線程(也就是ui線程)中進行更新界面顯示的工作。可以採用下面的方法之一來解決:
解決方案1:在activity.oncreate(bundle savedinstancestate)中創建一個handler類的實例, 在這個handler實例的handlemessage回調函數中調用更新界面顯示的函數。例如:
- public class ExampleActivity extends Activity {
- Handler h = null;
- @override
- public void onCreate(Bundle savedinstancestate){
- h = new Handler(){
- @override
- public void handleMessage(Message msg){
- // call update gui method.
- }
- };
- }
- }
在其它的函數中,利用 send族或post族函數向這個h發送或郵寄消息即可。
解決方案2:利用activity.runonuithread(runnable)
把更新ui的代碼創建在runnable中,然後在需要更新ui時,把這個runnable對象傳給activity.runonuithread(runnable)。 這樣runnable對像就能在ui程序中被調用。
正確寫法一 : 交由UI Thread處理
- import java.util.Timer;
- import java.util.TimerTask;
- import android.app.Activity;
- import android.os.Bundle;
- public class TestTimer extends Activity {
- Timer timer = new Timer();
- TimerTask task = new TimerTask(){
- public void run() {
- runOnUiThread(new Runnable(){
- @Override
- public void run() {
- setTitle("hear me?");
- }});
- }
- };
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- timer.schedule(task, 10000);
- }
- }
正確寫法二 :由Handler處理UI 更新。
- package com.test;
- import java.util.Timer;
- import java.util.TimerTask;
- import android.app.Activity;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- public class TestTimer extends Activity {
- Timer timer = new Timer();
- Handler handler = new Handler(){
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case 1:
- setTitle("hear me?");
- break;
- }
- super.handleMessage(msg);
- }
- };
- TimerTask task = new TimerTask(){
- public void run() {
- Message message = new Message();
- message.what = 1;
- handler.sendMessage(message);
- }
- };
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- timer.schedule(task, 10000);
- }
- }