Otto throw"对象已经注册" viewPager中的onResume

时间:2015-10-23 07:14:22

标签: android android-fragments otto

我在viewpager中有2个片段。当应用程序暂停时(按主页按钮,或低于其他应用程序)然后恢复,otto throw

 E/stack: task on pause
 E/stack: note on pause
 E/stack: onPause
 E/stack: onResume
 E/stack: task on resume
 E/stack: note on resume
 E/AndroidRuntime: FATAL EXCEPTION: main
 E/AndroidRuntime: java.lang.RuntimeException: Unable to resume activity {yarh.bigdig.bigdigtaskmanager/yarh.bigdig.bigdigtaskmanager.view.activity.SplashScreenActivity}: java.lang.IllegalArgumentException: Object already registered.
 E/AndroidRuntime:     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2575)
 E/AndroidRuntime:     at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2603)
 E/AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1237)
 E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:99)
 E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:137)
 E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:4745)
 E/AndroidRuntime:     at java.lang.reflect.Method.invokeNative(Native Method)
 E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Method.java:511)
 E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
 E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
 E/AndroidRuntime:     at dalvik.system.NativeStart.main(Native Method)
 E/AndroidRuntime:  Caused by: java.lang.IllegalArgumentException: Object already registered.
 E/AndroidRuntime:     at com.squareup.otto.Bus.register(Bus.java:222)
 E/AndroidRuntime:     at yarh.bigdig.bigdigtaskmanager.view.fragment.NoteListFragment.onResume(NoteListFragment.java:65)
 E/AndroidRuntime:     at android.support.v4.app.Fragment.performResume(Fragment.java:2008)
 E/AndroidRuntime:     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1119)
 E/AndroidRuntime:     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1259)
 E/AndroidRuntime:     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1241)
 E/AndroidRuntime:     at android.support.v4.app.FragmentManagerImpl.dispatchResume(FragmentManager.java:2063)
 E/AndroidRuntime:     at android.support.v4.app.FragmentController.dispatchResume(FragmentController.java:187)
 E/AndroidRuntime:     at android.support.v4.app.FragmentActivity.onResumeFragments(FragmentActivity.java:462)
 E/AndroidRuntime:     at android.support.v4.app.FragmentActivity.onPostResume(FragmentActivity.java:451)
 E/AndroidRuntime:     at android.support.v7.app.AppCompatActivity.onPostResume(AppCompatActivity.java:141)
 E/AndroidRuntime:     at android.app.Activity.performResume(Activity.java:5095)
 E/AndroidRuntime:     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2565)
 E/AndroidRuntime:     at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2603) 
 E/AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1237) 
 E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:99) 
 E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:137) 
 E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:4745) 
 E/AndroidRuntime:     at java.lang.reflect.Method.invokeNative(Native Method) 
 E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Method.java:511) 
 E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 
 E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 
 E/AndroidRuntime:     at dalvik.system.NativeStart.main(Native Method) 

PagerAdapter片段

public class BodyHolderFragment extends Fragment{


    @Bind(R.id.tabs) PagerSlidingTabStrip tabs;
    public @Bind(R.id.video_body_pager) ViewPager pager;
    public MyPagerAdapter pagerAdapter;


    @Override
    public View onCreateView(
        LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState
    ){
        View view = inflater.inflate(R.layout.fragment_body_holder, container, false);
        ButterKnife.bind(this, view);
        initPagerStrip();
        return view;

    }


    @Override
    public void onDestroyView(){
        super.onDestroyView();
        ButterKnife.unbind(this);
    }


    public void initPagerStrip(){

        String[] names =
            new String[]{getString(R.string.body_holder_tasks), getString(R.string.body_holder_notes)};
        pagerAdapter = new MyPagerAdapter(getFragmentManager(), names);
        pager.setAdapter(pagerAdapter);
        final int pageMargin = (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP, 4, getResources().getDisplayMetrics()
        );
        pager.setPageMargin(pageMargin);
        pager.setPageMarginDrawable(R.color.overflowDialogDivider);
        tabs.setViewPager(pager);

    }


    public class MyPagerAdapter extends FragmentPagerAdapter{


        private String[] pages;


        public MyPagerAdapter(
            FragmentManager fm, String[] pages
        ){
            super(fm);
            this.pages = pages;
        }


        @Override
        public Fragment getItem(int position){

            Bundle b = new Bundle();
            Fragment f;
            switch(position){
                case 0:
                    f = new TaskListFragment();
                    f.setArguments(b);

                    break;
                case 1:
                    f = new NoteListFragment();
                    f.setArguments(b);

                    break;
                default:
                    f = new TaskListFragment();
                    f.setArguments(b);
                    break;
            }
            return f;
        }


        @Override
        public int getCount(){

            return 2;

        }


        @Override
        public CharSequence getPageTitle(int position){
            return pages[position];
        }

    }
}

并且每个片段都有

  @Override public void onPause() {
    super.onPause();
    Log.e("stack", "note on pause");
    BusProvider.getInstance().unregister(true);
  }

  @Override public void onResume() {
    super.onResume();
    Log.e("stack", "note on resume");

    getLoaderManager().initLoader(0, null, cursorLoader);
    BusProvider.getInstance().register(this);
  }

5 个答案:

答案 0 :(得分:7)

在onResume / onPause上注册/取消注册总线不应该导致这种情况,但如果有人在任何情况下都希望避免这种情况,那么请尝试对其进行子类化。

public class YourBus extends Bus{
    private ArrayList registeredObjects = new ArrayList<>();

    @Override
    public void register(Object object) {
        if (!registeredObjects.contains(object)) {
            registeredObjects.add(object);
            super.register(object);
        }
    }

    @Override
    public void unregister(Object object) {
        if (registeredObjects.contains(object)) {
            registeredObjects.remove(object);
            super.unregister(object);
        }
    }
}

注意:这样做会隐藏程序员错误,因为在任何注册/取消注册的情况下,此代码都不会引发异常。

答案 1 :(得分:4)

我对 viewPager 中的片段有同样的问题,我的解决方案是注册片段的总线,当前可见,只需覆盖 setUserVisibleHint

private boolean isRegistered = false;
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        if (!isRegistered) {
            BusProvider.getInstance().register(this);
            isRegistered = !isRegistered;
        }
    } else {
        if (isRegistered) {
            BusProvider.getInstance().unregister(this);
            isRegistered = !isRegistered;
        }
    }
}

答案 2 :(得分:1)

我有类似的情况,当我在ViewPager中的几个片段上注册和取消注册Otto时,我遇到了不一致的崩溃,并且还通过推送通知深入链接到屏幕。它们并不总是完美配对。我有一些正常注册的后台服务,但我也想注册当前可见的片段。因为我只想要一个注册,我将此代码添加到我的总线包装器类。它不允许双(非)寄存器。

private Object currentScreen;

public void registerCurrentScreen(Object object) {
    if (currentScreen != null) {
        bus.unregister(currentScreen);
    }
    currentScreen = object;
    bus.register(object);
}

public void unregisterCurrentScreen(Object object) {
    if (currentScreen != null) {
        bus.unregister(object);
    } 
    currentScreen = null;
}

答案 3 :(得分:0)

我之前没有使用ViewPager,但Otto不允许注册两次。所以我在register()之前写了注册标志并检查 您最好也可以unregister()致电Fragment#onDestroyView()

  private boolean isBusRegistered;

  protected void registerBus() {
    if (!isBusRegistered) {
      Log.v(TAG, "registerBus: " + this);
      BusProvider.getInstance().register(this);
      isBusRegistered = true;
    }
  }

  protected void unregisterBus() {
    if (isBusRegistered) {
      Log.v(TAG, "unregisterBus: " + this);
      BusProvider.getInstance().unregister(this);
      isBusRegistered = false;
    }
  }

答案 4 :(得分:0)

无法解决该问题。切换到eventbus,因为它没有这个问题。