2011-11-18 127 views
6

我正在開發一個android應用程序,並且我有一個啓動/暫停特定模擬過程的按鈕。在此過程正在運行時,我需要實時輸出一些數據。但是當我爲模擬創建一個新線程時,我無法從該線程訪問視圖(讓它爲TextView),因爲它們只能從創建它們的線程訪問。另一方面,新線程是必需的,因爲否則用戶在模擬運行時將無法做任何事情(例如,按其他一些按鈕)。在這種情況下創建新服務還需要創建一個新線程。我應該如何解決這個問題?從其他線程訪問視圖(Android)

+0

你檢查出['AsyncTask'(HTTP://開發商.android.com/reference/android/os/AsyncTask.html)類?它是一個實用工具類,可幫助您輕鬆創建不同的線程並相應地更新UI元素。在這種情況下,您可以使用它的'publishProgress()'和'onProgressUpdate()'方法。 – 2011-11-18 13:30:53

回答

5

您可以處理它在許多方面,

  1. 嘗試使用的AsyncTask在此,您後臺工作doInBackGround()方法做,你的UI將不會阻止你也可以通過publishProgress()和onProgressUpdate()訪問您通過其上下文調用AsyncTask的Activity的視圖。

  2. 如果您使用的是簡單的線程然後使用處理程序或消息或runOnUiThread可以更新主線程的視圖。

但是,in your way I think AsyncTask is best for you.

2

您可以用android.os.Handler來解決問題。 Handler實例綁定到創建它的線程,您可以將Runnables發佈給它,並且它將在綁定到的線程中執行它們。例如:

import android.os.Handler; 
import android.widget.TextView; 

public class MyActivity extends Activity { 
    private Handler uiHandler; 
    private TextView simulationStatus; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
    ... 
    uiHandler = new Handler(); 
    ... 
    simulationStatus = (TextView) findViewById(R.id.simulationStatus); 
    ... 
    } 

    // This method is to be executed on the simulation thread. 
    public void simulate() { 
    ... 
    final String simulationStatusText = ...; 
    ... 
    uiHandler.post(new Runnable() { 
     @Override 
     public void run() { 
     // This is run on the UI thread. 
     simulationStatus.setText(simulationStatusText); 
     ... 
     } 
    }); 
    } 

    ... 
} 

您也可以使用AsyncTask。例如查看鏈接。

1

將活動傳遞到您的線程,並從內部使用它來訪問您的視圖。

// from your activity: 
myExternalThread = new MyCustomCode(this); // <-- activity passed 

// your "simulation process" constructor: 
public MyCustomCode(Activity parent) { 
    this.parent = parent; 
} 

// and when you want to access views: 
parent.runOnUiThread(new Runnable() { 
    @Override 
    public void run() { 
     parent.findViewById(R.id.text_view); 
     ... do something to your UI ... 
    } 
}); 

我創建這些外部任務的首選方法是使用AsyncTask(那麼你不必擔心runOnUiThread,還有其他好處)。我不知道它是否適用於你的案件,但你應該檢查出來。

+0

爲什麼是-1?任何解釋? – Guillaume

1

你必須存儲你是想確實顯示爲公共變種,讓你的主題通過Handler.post(可運行) 在運行的代碼中調用一個Runnable數據()方法可以訪問文本視圖

2

它們可以被訪問但只能是隻讀的。你的意思是你想觸發視圖上線程的變化。在工作線程(非UI)中,這些更改無法觸發,您需要使用.runOnUiThread()或使用Handlers。點在哪裏,你想展示的東西,如更新.runOnUiThread()TextView的使用這些,

例子:

myThread = new Thread() 
     { 

      @Override 
      public void run() { 
       //yourOperation 
       MyActivity.this.runOnUiThread(new Runnable(){ 

        @Override 
        public void run() { 
         if(e!=null) 
         { 
          myTextView.setText("something"); 
         } 

        }}); 
       super.run(); 
      } 
     }; 
     myThread.start(); 
+0

是否真的有可能只讀取非ui線程中的視圖?我感興趣的是使用位圖drawingCache = view.getDrawingCache()從視圖中讀取位圖,但我不斷收到異常:CalledFromWrongThreadException:只有創建視圖層次結構的原始線程可以觸及其視圖。 – Giorgio

相關問題