2010-11-09 58 views
0

因此,我收到一個錯誤,我正在從錯誤的線程更新UI。這當然不是我的意圖。我的情況很長,但我會盡量用代碼片斷來做到這一點。我的最終目標是在單獨的線程中運行昂貴的任務,並在發佈過程中發佈更新,最後發佈到我的listView。如何通過處理程序更新UI

public class test extends Activity { 

    private ArrayAdapter<String> _mOutArrayAdapter; 
    private ListView _mOutView; 
    private EditText _mCmdEditText; 
    private Button _mRunButton; 
    private Interpreter _interpreter; 

    // Need handler for callbacks to the UI thread 
    public final Handler _mHandler = new Handler() { 
    public void handleMessage(Message msg) { 
     _mOutArrayAdapter.add(msg.getData().getString("text")); 
    }; 
    }; 

    // Create runnable for posting 
    final Runnable mUpdateResults = new Runnable() { 
     public void run() { 
      updateResultsInUi(); 
     } 
    }; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     _interpreter = new Interpreter(true); 

     _mOutView = (ListView)findViewById(R.id.out); 
     _mCmdEditText = (EditText)findViewById(R.id.edit_command); 
     _mRunButton = (Button)findViewById(R.id.button_run); 

     _mOutArrayAdapter = new ArrayAdapter<String>(this, R.layout.message); 
     _mOutView.setAdapter(_mOutArrayAdapter); 
     _mOutArrayAdapter.clear(); 
     _interpreter.setOutputAdapter(_mOutArrayAdapter); 

     Thread t = new Thread() { 
      public void run() { 
       _mResults = _interpreter.executeExpression("startup;",_mHandler); 
       _mHandler.post(mUpdateResults); 
      } 
     }; 
     t.start(); 

    ); 

然後裏面inpterpreter我這樣做:

public class Interpreter 
{ 

    private static Handler _mHandler; 

    public String executeExpression(String expression, Handler handler) 
    { 
     _mHandler = handler; 

     //Do a bunch of stuff that sometimes calls displayText from this class or from others 

     return answer; 
    } 

    public void displayText(String text) 
    { 
     Message msg = new Message(); 
     Bundle bndl = new Bundle(); 
     bndl.putString("text", text); 
     msg.setData(bndl); 
     _mHandler.dispatchMessage(msg); 
    } 
} 

最終答案作品的展示。 dispatchMessage最終觸發了handleMessage,但它拋出了一個錯誤,我無法從UI線程之外修改UI,我知道這是非法的。那麼,我做錯了什麼?

謝謝!

+0

嘗試使用異步任務和其他人說,不知道你的代碼是做 – jonney 2010-11-09 17:17:44

+0

你說得對,使用SendMessage發送在處理程序的的handleMessage接收的消息。 – 2010-11-09 18:45:21

回答

2

我強烈建議你堅持使用AsyncTask(或者其中一個droid-fu版本,如果你需要旋轉/背景支持的話),除非你知道你在做什麼。它會幫助你清楚地跟蹤你的UI線程中運行的代碼以及後臺任務中的代碼,併爲你節省很多處理你自己可能導致的Thread s和Handler的混淆。

+0

我一直在尋找與AsyncTasks與線程之間的折衷。你知道爲什麼顯示的例子不起作用嗎? – corbin 2010-11-09 16:06:50

+0

你的代碼非常混亂,我們真的不知道那裏發生了什麼。至少我不能 – Falmarri 2010-11-09 16:35:24

+1

我堅持使用線程有幾個原因。我希望更簡單的例子能夠得到幫助。我的問題是調用dispatchMessage而不是sendMessage ... oops – corbin 2010-11-10 06:18:06

3
_mHandler.dispatchMessage(msg); 

dispatchMessage()會導致Handler在當前線程上運行。 http://developer.android.com/reference/android/os/Handler.html

DispatchMessage函數(消息MSG)這裏

手柄系統消息。

您應該使用_mHandler.sendMessage(msg);它會將消息放入由聲明處理程序的線程運行的隊列中。

的sendMessage(消息MSG)

在當前時間之前的所有未決消息後推的消息到消息隊列的末尾。

+0

dispatch!=發送......明顯區別/ s。這隻會浪費我幾小時的時間來找出我的處理程序不工作的原因。謝謝克里斯。 – GDanger 2014-05-01 21:15:36

1

Handler的post方法在參數中需要一個Runnable對象,並調度該可運行塊的執行。相反,您可以使用Handler.sendEmptyMessage()或Handler.sendMessage()向Handler發送消息。你的代碼,以便更改爲以下幾點:

Thread t = new Thread() { 
      public void run() { 
       _mResults = _interpreter.executeExpression("startup;",_mHandler); 
       Message msg= _mHandler.obtainMessage(); 
       msg.obj= _mResults; 
       _mHandler.sendMessage(msg); 
      } 
     }; 
相關問題