0

更新 1

我又做了一些调试,发现构造函数是从主 UI 线程运行的,但是 handleMessage(Message) 方法是在我创建的线程上运行的,这与我对 Handlers 的理解完全矛盾。

问题

我已经在 Android 上工作了一段时间,但遇到了一个似乎没有记录的问题。我没有对我的代码做任何特别的事情。我似乎无法让我的应用程序从处理程序的 handleMessage 方法创建任何 UI 元素,例如警报对话框和 Toast 消息。

此外,我得到一个“线程没有调用 Looper.prepare()”异常。但是,我相信我什至不需要调用 Looper.prepare() ,因为我没有在 Thread 对象内创建 Handler 。我在主 UI 线程中调用构造函数,然后将其传递给新线程的构造函数。

我的期望

我应该会看到 Toast 消息和警报对话框。

实际发生了什么

没有。我在应用程序上运行了调试器,发现 JVM 确实启动了线程。调用 run 方法并分派消息。处理程序处理该方法,我运行了创建 AlertDialog 以及 Toast 消息的所有方法,但没有显示任何内容。

我在运行 4.2 的模拟器、运行 4.0.4 的朋友的三星 Galaxy S3 和运行 2.3.5 的我自己的 Droid X2 上运行了这个应用程序。

程序流程

  1. 我在 UI 线程上创建了一个处理程序。
  2. 我创建并启动一个线程,它将向处理程序发送一条消息。
  3. 处理程序将处理消息

源代码

http://pastebin.com/cRfaW7b0

package com.nguyenmp.ErrorTest;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MyActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //Init the UI
        setContentView(R.layout.main);

        //Create a new handler, passing it the current activity context
        final Handler handler = new MyHandler(MyActivity.this);

        //Bind a listener to the button on the UI
        View view = findViewById(R.id.button);
        view.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                //Start a new thread that will send a message to that handler
                new MyThread(handler).start();
            }

        });
    }

    private class MyThread extends Thread {
        private final Handler mHandler;

        MyThread(Handler handler) {
            mHandler = handler;
        }

        @Override
        public void run() {
            //Dispatch message to UI thread asynchronously
            Looper.prepare();
            mHandler.dispatchMessage(mHandler.obtainMessage());
        }
    }

    private class MyHandler extends Handler {
        private final Context mContext;

        MyHandler(Context context) {
            mContext = context;
        }

        @Override
        public void handleMessage(Message msg) {
            //Show that we got the message
            AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
            builder.setTitle("HelloWorld");
            builder.setMessage("It worked!");
            builder.show();

            //Another variant of showing that we got the message
            Toast.makeText(mContext, "Message Received", Toast.LENGTH_SHORT).show();

            System.out.println("Yeah");
        }
    }
}
4

2 回答 2

1

您应该使用http://developer.android.com/reference/android/os/Handler.html#sendMessage(android.os.Message) 发送稍后将由 handleMessage 处理的消息。

于 2013-02-19T06:40:49.563 回答
0

问题是我正在调用 dispatchMessage(Message) ,它会在当前线程上立即执行。我应该一直在使用 sendMessage(Message) 它将给定的消息排入最初创建处理程序的原始线程的消息队列中。

于 2013-02-19T06:01:24.763 回答