Android线程,处理程序,handleMessage:从外部类文件中的可运行线程更新UI线程

时间:2013-07-23 19:07:04

标签: java android multithreading handler ui-thread

首先,我对Android很陌生,所以请光临我:)

背景: 我正在尝试将Java(非GUI)程序转换为在Android上运行。为简单起见,我们假设此程序包含以下文件:

DSGen.java,SInfer.java,Main.java

在Main()方法中,每个类DSGen和SInfer的对象都被初始化并传递给新的Threads并启动。此外,每个类DSGen和SInfer都使用public void run()方法实现Runnable,并且两个run方法都将文本输出到system.out.println()。

线程1.生成100个随机数据值 线程2.对生成数据的100个值进行计算(输出100个结果)

在该程序的Android版本中,我知道UI线程处理所有UI更新。 所以在我的MainActivity.java文件中,我试图声明一个Handler来接收来自"线程2的消息和输出数据"可用于更新MainActivity UI线程中的TextView。当我按下Android UI上的开始按钮时,应用程序开始执行。

问题: 当我运行此应用程序时,我的TextView不会更新,直到处理结束。我还注意到并非所有输出都更新到我的TextView,只有40/100的计算实际上是用于TextView。

程序的实际代码很长,我认为最好只包含与SInfer类的线程,处理程序和run方法相关的部分。

我希望有人可以给我一个伪代码示例或解决方案来处理多个线程,其中runnable方法在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());
        }
    }
}

2 个答案:

答案 0 :(得分:0)

您正在运行Thread.sleep(10000);在主线程中(在UI线程中调用OnClick),因此在此10秒内无法在UI中更新任何内容。 尝试在单独的线程中调用runFSI方法。

答案 1 :(得分:0)

使用AsyncTask

覆盖doInBackground()来处理所有后台计算

重写onProgressUpdate(),以便在线程使用publishProgress()方法运行时与UI线程对话。

并覆盖onPostExecute()以在UI线程上执行任何最终操作。