androidandroid-fragmentsotto

Otto throw "Object already registered" onResume in viewpager


I have 2 fragments in viewpager. When application is paused (press home button, or below other application) and then resumed, 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 fragment

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];
        }

    }
}

and each fragment has

  @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);
  }

Solution

  • I had same problem for fragments inside the viewPager, my solution is to register bus for fragment, which is currently visible, just override 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;
            }
        }
    }