我在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);
}
答案 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,因为它没有这个问题。