在背面按下,返回到具有Fragments的RecyclerView会导致IllegalArgumentException

时间:2015-02-06 13:12:52

标签: android android-fragments android-viewpager android-recyclerview onbackpressed

我在活动中有2个片段。第一个片段A有一个recyclerview,其中一行包含viewpager。此ViewPager具有使用FragmentStatePagerAdapter创建的多个片段(每个页面都是片段)。现在点击我将用户导航到片段B的操作项。这里我使用FragmentTransaction的replace()方法将片段A替换为B.现在按下片段B上的后退按钮,应用程序崩溃,但有以下异常:

02-06 18:21:49.038: W/System.err(6916): java.lang.IllegalArgumentException: No view found for id 0x7f110209 (com.example:id/vPager) for fragment VFragment{da512cf #0 id=0x7f110209}
02-06 18:21:49.038: W/System.err(6916):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:939)
02-06 18:21:49.038: W/System.err(6916):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1126)
02-06 18:21:49.038: W/System.err(6916):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1108)
02-06 18:21:49.038: W/System.err(6916):     at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1917)
02-06 18:21:49.038: W/System.err(6916):     at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1800)
02-06 18:21:49.038: W/System.err(6916):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:967)
02-06 18:21:49.038: W/System.err(6916):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1126)
02-06 18:21:49.038: W/System.err(6916):     at android.support.v4.app.BackStackRecord.popFromBackStack(BackStackRecord.java:957)
02-06 18:21:49.039: W/System.err(6916):     at android.support.v4.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1541)
02-06 18:21:49.039: W/System.err(6916):     at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:502)
02-06 18:21:49.039: W/System.err(6916):     at android.support.v4.app.FragmentActivity.onBackPressed(FragmentActivity.java:176)
02-06 18:21:49.039: W/System.err(6916):     at android.support.v7.app.ActionBarActivity.onBackPressed(ActionBarActivity.java:298)
02-06 18:21:49.039: W/System.err(6916):     at com.example.MainActivity.onBackPressed(MainActivity.java:2049)
02-06 18:21:49.039: W/System.err(6916):     at android.app.Activity.onKeyUp(Activity.java:2453)
02-06 18:21:49.039: W/System.err(6916):     at android.view.KeyEvent.dispatch(KeyEvent.java:2633)
02-06 18:21:49.039: W/System.err(6916):     at android.app.Activity.dispatchKeyEvent(Activity.java:2704)
02-06 18:21:49.039: W/System.err(6916):     at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2221)
02-06 18:21:49.039: W/System.err(6916):     at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:3918)
02-06 18:21:49.039: W/System.err(6916):     at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3880)
02-06 18:21:49.039: W/System.err(6916):     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
02-06 18:21:49.039: W/System.err(6916):     at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3502)
02-06 18:21:49.039: W/System.err(6916):     at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
02-06 18:21:49.039: W/System.err(6916):     at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3578)
02-06 18:21:49.039: W/System.err(6916):     at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3476)
02-06 18:21:49.039: W/System.err(6916):     at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3635)
02-06 18:21:49.039: W/System.err(6916):     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
02-06 18:21:49.039: W/System.err(6916):     at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3502)
02-06 18:21:49.039: W/System.err(6916):     at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
02-06 18:21:49.039: W/System.err(6916):     at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3476)
02-06 18:21:49.039: W/System.err(6916):     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
02-06 18:21:49.039: W/System.err(6916):     at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3502)
02-06 18:21:49.039: W/System.err(6916):     at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
02-06 18:21:49.039: W/System.err(6916):     at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3611)
02-06 18:21:49.039: W/System.err(6916):     at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:3772)
02-06 18:21:49.039: W/System.err(6916):     at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2208)
02-06 18:21:49.039: W/System.err(6916):     at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:1849)
02-06 18:21:49.039: W/System.err(6916):     at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:1840)
02-06 18:21:49.039: W/System.err(6916):     at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:2185)
02-06 18:21:49.039: W/System.err(6916):     at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:141)
02-06 18:21:49.039: W/System.err(6916):     at android.os.MessageQueue.nativePollOnce(Native Method)
02-06 18:21:49.039: W/System.err(6916):     at android.os.MessageQueue.next(MessageQueue.java:143)
02-06 18:21:49.039: W/System.err(6916):     at android.os.Looper.loop(Looper.java:122)
02-06 18:21:49.040: W/System.err(6916):     at android.app.ActivityThread.main(ActivityThread.java:5221)
02-06 18:21:49.040: W/System.err(6916):     at java.lang.reflect.Method.invoke(Native Method)
02-06 18:21:49.040: W/System.err(6916):     at java.lang.reflect.Method.invoke(Method.java:372)
02-06 18:21:49.040: W/System.err(6916):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
02-06 18:21:49.040: W/System.err(6916):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

请注意,如果我使用FragmentTransaction的add()方法添加片段B,那么反压不会导致应用崩溃。从上面的崩溃日志看起来甚至在recyclerview更新其视图之前,viewpager子片段正试图找到viewpager。如何在recyclerview再次准备好之前防止这种情况或延迟片段状态保留过程?

1 个答案:

答案 0 :(得分:3)

我遇到了类似的问题(我没有使用替换,但我正在使用添加),我找到了解决方案。您需要在onCreateView()或onActivityCreated()中为父片段(片段A)分离嵌套片段。然后,在该片段的绑定调用中,您可以重新附加。这是一些示例代码:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    FragmentManager fragmentManager = getChildFragmentManager();
    Fragment fragment = fragmentManager.findFragmentById(R.id.nested_fragment);
    if (fragment != null) {
        fragmentManager.beginTransaction().detach(fragment).commit();
        fragmentManager.executePendingTransactions();
    }
}

请注意,调用executePendingTransactions()非常重要。如果我正确理解了这个问题,那是因为onActivityCreated()正在作为FragmentTransaction的一部分进行处理。如果不调用executePendingTransactions,它将继续处理嵌套片段,然后再处理分离调用。

然后在适配器的bind调用中,执行以下操作:

public void bindNestedFragment(View view) {
    Fragment fragment = mFragmentManager.findFragmentById(R.id.nested_fragment);
    if (fragment == null) {
        // Create/add fragment here
    } else {
        mFragmentManager.beginTransaction.attach(fragment).commit();
    }
}

您必须通过某种方式让您的Adapter访问片段管理器(我只是在构造函数中传递它)。希望这有帮助!