Android 如何知道Otto用户已注册

Android 如何知道Otto用户已注册,android,otto,Android,Otto,我在用方格。我的订户类在Activity/FragmentonStart和onStop方法中注册 然而,有时我会犯这个错误 原因:java.lang.IllegalArgumentException:缺少事件处理程序 对于带注释的方法。类EventListener是否已注册? 在com.squareup.otto.Bus.unregister(Bus.java:289) 我很肯定我的班级已经注册了。有没有一种方法可以知道这个类是否已注册 // in a Fragment or Activity

我在用方格。我的订户类在Activity/Fragment
onStart
onStop
方法中注册

然而,有时我会犯这个错误

原因:java.lang.IllegalArgumentException:缺少事件处理程序 对于带注释的方法。类EventListener是否已注册? 在com.squareup.otto.Bus.unregister(Bus.java:289)

我很肯定我的班级已经注册了。有没有一种方法可以知道这个类是否已注册

// in a Fragment or Activity
@Override
public void onStart() {
    super.onStart();

    Bus bus = new Bus();
    bus.register(eventListener); // register the class where the annotated @Subscribe method is
    bus.isRegistered(); // ??
}

如果您试图
取消注册()
一个尚未注册或正在取消注册两次的对象,则会收到此错误消息


由于注册是基于对象的,您可以简单地将一个
布尔isRegistered
成员添加到那些通常的生命周期不能保证寄存器和注销正确配对的类中。

就像@laalto所说的,在总线API中没有这样的方法。 下面是我如何实现布尔值isRegistered的

//  implement as a Singleton class
public class EventListener {

    // necessary to avoid to unregister a non-registered instance . Since EventListener is a Singleton
    private static boolean isRegistered;

    public void setIsRegistered(final boolean registered){
        isRegistered = registered;
    }

    public boolean isRegistered(){
        return isRegistered;
    }

    @Subscribe
    public void onTrackingEvent(final TrackingEvent event) {
        // to do
    }
}
现在在片段或活动中,注册/注销到
com.squareup.otto.Bus

// in a Fragment or Activity
@Override
public void onStart() {
    super.onStart();
    // eventListener is the class containing the @Subscribe method
    bus.register(eventListener);
    eventListener.setIsRegistered(true);
}

@Override
public void onStop() {
    super.onStop();
    if (eventListener.isRegistered()) {
        bus.unregister(eventListener);
        eventListener.setIsRegistered(false);
    }
}

如上所述,Otto的API不提供询问潜在订户是否已向
总线注册的方法。fail fast语义旨在让您立即注意到代码中存在对
register()
和/或
unregister()
的未配对调用,而不是让这种情况继续存在,并在以后导致一些潜在的意外副作用

虽然我同意这种方法,但最近我发现自己在自己的一个项目中几乎没有时间来追踪这个问题,所以我实施了一个基于Kotlin的快速而肮脏的小黑客,使用扩展功能给自己一些喘息的空间。以下内容包含与重复注册相关的
IllegalArgumentExceptions
,以及尝试注销尚未注册的订阅者。它非常脆弱,同时避免异常处理会更有效,但这至少需要更少的脚手架来维护组件的注册状态:

fun Bus.registerSafely(`object`: Any) {
    try {
        this.register(`object`)
    } catch(t: Throwable) {
        when(t) {
            is IllegalArgumentException -> {
                val message = t.message

                if(message != null && message.contains("Object already registered", ignoreCase = true)) {
                    /* quietly ignore this... */
                } else {
                    throw t
                }
            }

            else -> throw t
        }
    }
}

fun Bus.unregisterSafely(`object`: Any) {
    try {
        this.unregister(`object`)
    } catch(t: Throwable) {
        when(t) {
            is IllegalArgumentException -> {
                val message = t.message

                if(message != null && message.contains("Missing event handler", ignoreCase = true)) {
                    /* quietly ignore this... */
                } else {
                    throw t
                }
            }

            else -> throw t
        }
    }
}

谢谢@Iaalto,我已经有了布尔运算的想法。但是我只是想知道Square的人是否制定了一种特殊的方法不,总线API本身没有这种方法。大多数情况下,活动/片段/服务/任何生命周期都保证注册/取消注册调用是成对的。对于极少数不可用的情况,请在类中使用布尔值。