Java Android线程、处理程序、handleMessage:从外部类文件中的可运行线程更新UI线程
背景: 我正在尝试将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类的线程、处理程序和run方法相关的部分 我希望有人能给我一个伪代码示例或解决方案,用于处理多个线程,其中可运行方法在两个不同的类文件(而不是MainActivity中的内部类)中声明,并且可以通过将一条消息从一个线程传递回UI线程来更新UI 提前谢谢你Java Android线程、处理程序、handleMessage:从外部类文件中的可运行线程更新UI线程,java,android,multithreading,handler,ui-thread,Java,Android,Multithreading,Handler,Ui Thread,背景: 我正在尝试将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
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代码的遗留代码)
你正在运行线程。睡眠(10000);在主线程中(在UI线程中调用OnClick),因此在这10秒内UI中无法更新任何内容。 尝试在单独的线程中调用您的runFSI方法。使用 重写doInBackground()以处理所有背景计算 重写onProgressUpdate()以在UI线程使用publishProgress()方法运行时与该线程进行对话
并重写onPostExecute(),以在UI线程上执行任何最后的操作。感谢您指出这一点。在更新TextView之前,睡眠肯定会延迟10秒!正如建议的那样,如果我为FSI创建单独的线程(称为线程0),这反过来又会创建两个以上的线程。其中,线程2依赖于线程1生成的数据。最好的办法是什么?为FSI创建一个内部类?另外,我是否只传递一个对uiHandler的引用,该引用可以依次传递到线程2中,以便将结果作为消息发送?再次感谢!
@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());
}
}
}