Android 我无法从处理程序创建UI元素';s handleMessage呼叫 更新1
我做了更多的调试,发现构造函数是从主UI线程运行的,而handleMessage(Message)方法是在我创建的线程上运行的,这与我对处理程序的理解完全矛盾 问题 我已经在安卓上工作了一段时间,我遇到了一个似乎没有记录的问题。我的代码没有做任何特殊的事情。我似乎无法让我的应用程序从处理程序的handleMessage方法创建任何UI元素,例如警报对话框和Toast消息 此外,我还得到一个“线程未调用Looper.prepare()”异常。但是,我认为我甚至不需要调用Looper.prepare(),因为我没有在Thread对象内部创建处理程序。我在主UI线程中调用构造函数,然后将其传递给新线程的构造函数 我所期望的 我应该会看到一个祝酒词以及一个警告对话框 到底发生了什么 没什么。我在应用程序上运行了调试器,发现JVM确实启动了线程。调用run方法并调度消息。处理程序处理该方法,我运行了创建AlertDialog和Toast消息的所有方法,但没有显示任何内容 我已经在运行4.2的模拟器上运行了这个应用程序,我朋友的三星Galaxy S3运行了4.0.4,我自己的Droid X2运行了2.3.5 程序流程Android 我无法从处理程序创建UI元素';s handleMessage呼叫 更新1,android,Android,我做了更多的调试,发现构造函数是从主UI线程运行的,而handleMessage(Message)方法是在我创建的线程上运行的,这与我对处理程序的理解完全矛盾 问题 我已经在安卓上工作了一段时间,我遇到了一个似乎没有记录的问题。我的代码没有做任何特殊的事情。我似乎无法让我的应用程序从处理程序的handleMessage方法创建任何UI元素,例如警报对话框和Toast消息 此外,我还得到一个“线程未调用Looper.prepare()”异常。但是,我认为我甚至不需要调用Looper.prepare
问题是我调用了dispatchMessage(Message),它在当前线程上即时执行。我应该使用sendMessage(Message),它将给定的消息排队到最初创建处理程序的原始线程的消息队列中。您应该使用
发送稍后将由handleMessage处理的消息。如果您刚才调用了
handler.dispatchMessage()
,单击onClick
会怎么样?或者,您可以调用handler.post(Runnable r)
,Runnable将使Toast
或显示对话框。另外,请使用Log.d()
而不是System.out.println()
。这是我的应用程序的一个极其简化的版本,但我仍然遇到一个问题,即处理程序的handleMessage方法正在Main以外的其他线程中执行。例如,我的测试显示它在“pool-2-thread-1”上运行。在我的实际应用程序中,我正在创建一个自定义侦听器,该侦听器在后台使用处理程序来处理所有异步回调。问题是,由于某种原因,我无法将处理程序传递给我的线程并让它分派消息。也许我不了解自己程序的流程,或者我不了解处理程序是如何工作的。
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");
}
}
}