Android中Handler与消息处理的问题

6

我在我的应用程序中使用Handlers,在一个屏幕上,通过点击按钮会调用一些代码。为了调用那组代码,我向Handler发送消息并覆盖了handle messages方法。第一次点击按钮时,Handler正常工作并执行代码集。当我第二次点击按钮时,我遇到了以下异常。

05-03 09:45:25.703: ERROR/AndroidRuntime(1971): FATAL EXCEPTION: main
05-03 09:45:25.703: ERROR/AndroidRuntime(1971): android.util.AndroidRuntimeException: { what=1 when=7381217 obj=android.app.AlertDialog@462b5c58 } This message is already in use.
05-03 09:45:25.703: ERROR/AndroidRuntime(1971):     at android.os.MessageQueue.enqueueMessage(MessageQueue.java:171)
05-03 09:45:25.703: ERROR/AndroidRuntime(1971):     at android.os.Handler.sendMessageAtTime(Handler.java:457)
05-03 09:45:25.703: ERROR/AndroidRuntime(1971):     at android.os.Handler.sendMessageDelayed(Handler.java:430)
05-03 09:45:25.703: ERROR/AndroidRuntime(1971):     at android.os.Handler.sendMessage(Handler.java:367)
05-03 09:45:25.703: ERROR/AndroidRuntime(1971):     at com.mysnob.utils.MessageDialog$8.onClick(MessageDialog.java:93)
05-03 09:45:25.703: ERROR/AndroidRuntime(1971):     at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:158)
05-03 09:45:25.703: ERROR/AndroidRuntime(1971):     at android.os.Handler.dispatchMessage(Handler.java:99)
05-03 09:45:25.703: ERROR/AndroidRuntime(1971):     at android.os.Looper.loop(Looper.java:144)
05-03 09:45:25.703: ERROR/AndroidRuntime(1971):     at android.app.ActivityThread.main(ActivityThread.java:4937)
05-03 09:45:25.703: ERROR/AndroidRuntime(1971):     at java.lang.reflect.Method.invokeNative(Native Method)
05-03 09:45:25.703: ERROR/AndroidRuntime(1971):     at java.lang.reflect.Method.invoke(Method.java:521)
05-03 09:45:25.703: ERROR/AndroidRuntime(1971):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
05-03 09:45:25.703: ERROR/AndroidRuntime(1971):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
05-03 09:45:25.703: ERROR/AndroidRuntime(1971):     at dalvik.system.NativeStart.main(Native Method)

我理解在重复发送同一条消息时,会出现这个异常。但是我不知道如何解决这个问题,如果有人知道,请帮助我。

谢谢,

Rajapandian


你在handler中调用了removeMessages(what)并使用Message.obtainMessage(what)获取消息吗? - JAL
@JAL 我正在使用 Message.obtainMessage() 方法获取消息,我已经检查了 Message.obtainMessage(what) 但是没有找到类似的方法。 - Rajapandian
从文档中获取obtainMessage(int what)方法 与obtainMessage()相同,但它还设置了返回的Message的what成员。链接:http://developer.android.com/reference/android/os/Handler.html#obtainMessage(int) - JAL
可能是 Android Handler Message and ListView 的重复问题。 - laalto
使用obtainMessage(what)时,removeMessages(what)是不必要的。 - kupsef
根据@JAL的评论,应该使用HANDLER.obtainMessage()。 - VVB
4个回答

11

您永远不应该复用Message对象。如果您需要多次发送消息,则每次都要新建一个Message对象。


完全正确:)。我们只能使用一次消息引用。 - Abdul Mohsin

1
有一个辅助方法可以复制您的消息。 通过这个方法,您可以发送原始消息的副本,而不是重新发送相同的对象(如果之前仍在使用,这将失败)。
public static Message obtain (Message orig);

其他人建议从处理程序中删除消息并重新发送。这将解决异常问题,但您可能不希望这样做。删除和重新发送可能会导致未传递的消息丢失。这就是为什么我建议您复制您的消息。
检查您的消息,并确保您没有发送任何重复的消息。
更新:
为了清楚起见...您可以随意发送具有相同what(或其他相同参数)的消息。您唯一需要确保的是每次发送消息时都要创建新的Message。您无需删除任何内容,它将添加到处理程序的消息队列中。

我正在使用以下代码进行复制: Message message = Message.obtain(handler); message.obj = "准备中..."; handler.sendMessage(message); 但您仍将收到相同的错误消息:(此消息已在使用中) - mugume david
我已经做了这个一千次,而且我现在测试过了。它是有效的。你一定搞砸了什么。 - kupsef
嗯...这很有帮助。谢谢。 - Ankit Gupta

0
尝试每次创建新的消息实例,即使您可以发送相同的数据,但是每次都创建新的消息实例。展示不创建而使用的问题。例如:
Bundle bundle = new Bundle();
bundle.putString("SahittoEntryAddedDirect", "SahittoEntryAddedDirect");

builder.setPositiveButton("Finalize Adding", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialogInterface, int i) {
        Message msg = new Message();
        msg.setData(bundle);
        ReadBooksList.messageHandler.sendMessage(msg);
    }
});

               
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
    @Override
    public void onCancel(DialogInterface dialogInterface) {
        Message msg = new Message();
        msg.setData(bundle);
        ReadBooksList.messageHandler.sendMessage(msg);
    }
});

dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
    @Override
    public void onDismiss(DialogInterface dialogInterface) {
        Message msg = new Message();
        msg.setData(bundle);
        ReadBooksList.messageHandler.sendMessage(msg);
    }
});

           

-2
你需要从你的处理程序中删除消息。 看看我的例子:我使用这个处理程序向我的对话框(mDialog)发送消息。
/**
 * this property will help send messages to the dialog
 */
Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        mDialog.setMessage((String) msg.obj);
        removeMessages(0); //this is very important
    }
};

你不需要删除该消息,因为操作系统会自动处理。这是完全自动化的过程。 - kupsef

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接