【问题标题】:Android Threads, Handlers, handleMessage: Updating UI thread from runnable threads within external class filesAndroid 线程、处理程序、handleMessage:从外部类文件中的可运行线程更新 UI 线程
【发布时间】:2013-07-23 00:56:37
【问题描述】:

背景: 我正在尝试将 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());
        }
    }
}

【问题讨论】:

    标签: java android multithreading handler ui-thread


    【解决方案1】:

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

    【讨论】:

    • 感谢您指出这一点。在更新 TextView 之前,睡眠肯定会停滞 10 秒!正如建议的那样,如果我为 FSI 创建单独的线程(称为线程 0),这又会创建另外两个线程。其中线程 2 依赖于线程 1 生成的数据。最好的方法是什么?为 FSI 创建一个内部类?我是否也只是传递对 uiHandler 的引用,该引用又可以传递给线程 2,以便我可以将结果作为消息发送?再次感谢!
    【解决方案2】:

    考虑使用AsyncTask

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-21
      • 2013-08-02
      • 2019-09-10
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      • 2016-01-16
      • 2013-03-19
      相关资源
      最近更新 更多