使用带有保留片段的Otto时出现IllegalArgumentException

Niq*_*iqo 7 android android-lifecycle otto

我正在使用Otto 1.3.3,当我恢复我的应用程序时,我有时会得到IllegalArgumentException以下堆栈跟踪:

Caused by: java.lang.IllegalArgumentException: Producer method for type class 
com.couchsurfing.mobile.ui.setup
        .SessionProviderFragment$SessionConnectionStateChangeEvent found on 
        type class com.couchsurfing.mobile.ui.setup.SessionProviderFragment, 
        but already registered by type class 
        com.couchsurfing.mobile.ui.setup.SessionProviderFragment.
    at com.squareup.otto.Bus.register(Bus.java:194)
    at com.couchsurfing.mobile.ui.BaseRetainedFragment
       .onCreate(BaseRetainedFragment.java:20)
Run Code Online (Sandbox Code Playgroud)

SessionProviderFragment有它的实例保留,请找扩展的类如下所示:

public abstract class BaseRetainedFragment extends SherlockFragment {

    @Inject
    Bus bus;

    @Override
    public void onCreate(final Bundle state) {
        super.onCreate(state);
        ((CouchsurfingApplication) getActivity().getApplication()).inject(this);
        setRetainInstance(true);
        bus.register(this);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        bus.unregister(this);
        bus = null;
    }
}
Run Code Online (Sandbox Code Playgroud)

我试过使用bus.register(this)in onAttach()或者onCreate()没有改变这个问题.

Chr*_*rry 7

在公交车上注册onResume()的适当位置在,取消注册的适当位置是onPause()这样的:

public abstract class BaseRetainedFragment extends RoboSherlockFragment {
    @Inject private Bus bus;

    @Override
    public void onCreate(final Bundle state) {
        super.onCreate(state);
        setRetainInstance(true);
    }

    @Override
    public void onResume() {
        super.onResume();
        bus.register(this);
    }

    @Override
    public void onPause() {
        super.onDestroy();
        bus.unregister(this);
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,onDestroy()不能保证被调用.

您可能会对此发表评论并说,嘿Chris,如果我注册onResume()并且事件在我点击此方法之前被解雇,我将不会收到这些事件!你是对的,但这意味着你没有像你应该那样使用制作人.

另请注意,如果您使用roboguice-sherlock,则无需自己注射.你也不需要nullBus时候片段超出范围的垃圾收集器将清理你.


Niq*_*iqo 1

我为每个活动使用一个“保留片段”来保存 HTTP 会话请求的状态。我的问题是我没有以正确的方式实例化我的“保留片段”。

在我在 onCreate() 之前:

if (savedInstanceState == null) {
    sessionProviderFragment = new SessionProviderFragment();
    getSupportFragmentManager().beginTransaction().add(sessionProviderFragment,
        SessionProviderFragment.TAG).commit();
}
Run Code Online (Sandbox Code Playgroud)

SessionProviderFragment显然,当退出活动并稍后重新打开它时,上面的代码可能会创建几个。看来正确的方法是:

sessionProviderFragment = (SessionProviderFragment) getSupportFragmentManager()
    .findFragmentByTag(SessionProviderFragment.TAG);

// If not retained (or first time running), we need to create it.
if (sessionProviderFragment == null) {
    sessionProviderFragment = new SessionProviderFragment();
    getSupportFragmentManager().beginTransaction().add(sessionProviderFragment,
            SessionProviderFragment.TAG).commit();
}
if (savedInstanceState == null) {
    initUiFragment();
}
Run Code Online (Sandbox Code Playgroud)

我还在 BaseFragment 的 onResume/onPause 中移动了总线注册/取消注册,以确保我每次都会SessionProviderFragment在总线上注册一个。