首先我很新到Android,請與我:)裸Android的線程,處理程序的handleMessage:從運行的線程更新內外部類文件UI線程
背景: 我想轉換一個Java(非GUI)程序在Android上運行。爲簡單起見讓我們說該程序具有以下文件:
DSGen.java,SInfer.java,Main.java
在Main()方法,對象爲每個類DSGen和SInfer被初始化並通過進入新的線程並開始。同樣,每個DSGen和SInfer類都使用public void run()方法實現Runnable,並且兩個運行方法都將文本輸出到system.out.println()。
螺紋1.產生隨機數據的100個值 線索2使在100個值生成的數據(輸出100次的結果)
在我知道該程序的Android版本,該UI線程處理的所有計算UI更新。 因此,在我的MainActivity.java文件中,我試圖聲明一個處理程序來接收來自「具有輸出數據的線程2」的消息,該消息可用於更新MainActivity UI線程中的TextView。當我按下Android UI上的開始按鈕時,該應用程序開始執行。
問題: 當我運行這個應用程序時,我的TextView不會更新,直到處理結束。我還注意到,並非所有的輸出都更新爲我的TextView,只有40/100的計算實際上將其輸入到TextView中。
該程序的實際代碼很長,我認爲最好只包含與SInfer類的線程,處理程序和運行方法相關的部分。
我希望有人可以給我一個僞代碼示例或解決方案來處理多個線程,其中可運行的方法在2個不同的類文件(不是MainActivity中的內部類)中聲明,並且可以通過傳遞來自其中一個線程的消息返回到UI線程。
預先感謝您!
public class MainActivity extends Activity {
/* UI Elements */
private TextView output;
/* Thread Handler */
private Handler uiHandler;
/* Handle message override */
public class UIHandler extends Handler {
@Override
public void handleMessage(Message msg) {
output.append(msg.obj.toString());
super.handleMessage(msg);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_run_fsi);
output = (TextView) findViewById(R.id.displayTextView);
uiHandler = new UIHandler();
setStartButtonClickListener();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_run_fsi, menu);
return true;
}
private void setStartButtonClickListener() {
Button startButton = (Button) findViewById(R.id.startButton);
startButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
runFSI();
}
});
}
private void runFSI() {
// initialize SInfer and pass uiHandler
SInfer inferer = SInfer.getInstance(/*other variables*/, uiHandler);
// initialize DSGen
DSGenerator dsGen;
Thread t1 = new Thread(dsGen);
Thread t2 = new Thread(inferer);
t1.start();
t1.yield();
t2.start();
t2.yield();
try {
Thread.sleep(10000);
} catch (Exception e) {
}
inferer.stop();
dsGen.stop();
}
}
內部SInfer所述的運行方法如下(System.out的代碼被從原始Java代碼遺留)
@Override
public void run() {
// System.out.println("Inference: Thread started...");
while (stopFlag == false) {
try {
// System.out.println("SInference: run.........");
Thread.sleep(200);
inferenceResult = doInference();
/* Send result to UI thread */
Message msg = Message.obtain(uiHandler);
msg.obj = inferenceResult.toString();
uiHandler.sendMessage(msg);
} catch (InterruptedException e) {
// System.out.println(e.getMessage());
}
}
}
謝謝你指出這一點。在更新TextView之前,睡眠肯定會停止10秒。如所建議的如果我爲FSI創建單獨的線程(調用此線程0),然後又創建兩個線程。線程2依賴於線程1生成的數據。什麼是最好的方法?爲FSI創建一個內部類?我也只是傳遞一個對uiHandler的引用,它可以反過來傳遞給線程2,以便我可以將結果作爲消息發送出去?再次感謝! – iron3rd