背景:我正在尝试将 Java(非 GUI)程序转换为在 Android 上运行。为简单起见,假设该程序具有以下文件:
DSGen.java、SInfer.java、Main.java
在 Main() 方法中,每个 DSGen 和 SInfer 类的对象都被初始化并传递到新线程并启动。此外,DSGen 和 SInfer 类中的每一个都使用公共 void run() 方法实现 Runnable,并且两个 run 方法都将文本输出到 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线程返回到 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内部定义的run方法如下(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());
}
}
}