无法恢复嵌套片段状态

时间:2016-12-05 03:43:12

标签: java android android-fragments android-activity

我在恢复嵌套片段的状态时遇到问题。这是层次结构:

MainActivity

----> AlarmOverviewFragment(并不包含任何重要数据)

--------> AlarmFragment(保存数据)

我遇到的问题是当我最小化应用程序(按主页按钮)然后重新打开应用程序时,每次尝试从存储为Fragment实例之一的数组中获取数据时它都会崩溃onCreateView()内的变量。

令人沮丧的是,我将实例变量保存在onSaveInstanceState()中,但savedInstanceStateonCreateView()onCreate()中的onActivityCreated()始终为空。

显然,我在这里遗漏了一些巨大的东西,因为我尝试了很多在stackoverflow上找到的解决方案,但无济于事。这是一些相关的代码位:

保存实例数据:

@Override
public void onSaveInstanceState(Bundle outState) {
    outState.putInt("hour", this.hour);
    outState.putInt("window", this.window);
    outState.putInt("minutes", this.minutes);
    outState.putBooleanArray("days", this.days);
    super.onSaveInstanceState(outState);
}

尝试恢复数据失败

@Override
public void onCreate(Bundle savedInstanceState) {

    if (savedInstanceState != null) {
        /* Never happens */
        hour = savedInstanceState.getInt("hour");
        window = savedInstanceState.getInt("window");
        minutes = savedInstanceState.getInt("minutes");
        days = savedInstanceState.getBooleanArray("days");
    }
    super.onCreate(savedInstanceState);
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    if (savedInstanceState != null) {
        /* Also never happens */
    }
    super.onActivityCreated(savedInstanceState);
}

以防这是有用的,这里是堆栈跟踪:

E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: group12.wakemeup, PID: 22756
                  java.lang.RuntimeException: Unable to resume activity {group12.wakemeup/group12.wakemeup.MainActivity}: java.lang.NullPointerException: Attempt to read from null array
                      at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3121)
                      at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3152)
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1400)
                      at android.os.Handler.dispatchMessage(Handler.java:102)
                      at android.os.Looper.loop(Looper.java:148)
                      at android.app.ActivityThread.main(ActivityThread.java:5525)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
                   Caused by: java.lang.NullPointerException: Attempt to read from null array
                      at group12.wakemeup.AlarmFragment.onCreateView(AlarmFragment.java:113)
                      at android.support.v4.app.Fragment.performCreateView(Fragment.java:2087)
                      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1113)
                      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1295)
                      at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:801)
                      at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1682)
                      at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:388)
                      at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:607)
                      at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:181)
                      at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1237)
                      at android.app.Activity.performStart(Activity.java:6288)
                      at android.app.Activity.performRestart(Activity.java:6334)
                      at android.app.Activity.performResume(Activity.java:6339)
                      at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3110)
                      at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3152) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1400) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:148) 
                      at android.app.ActivityThread.main(ActivityThread.java:5525) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620) 

修改

额外信息

每个AlarmFragment都会动态添加,并通过View.generateViewId()提供唯一ID,因此我不确定如何在MainActivity中保存每个片段。另外值得一提的是,我使用FragmentPagerAdapter来处理标签/滑动(此应用中还有其他概述片段,但我将它们排除在外,因为它们不会导致我出现问题)。我听说有一种方法可以使用ViewPager来保存状态,也许还有一个FragmentPagerAdapter

3 个答案:

答案 0 :(得分:1)

尝试将片段保存在您的活动中

private YourFragment yourFragment;

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    //Save the fragment instances
    getFragmentManager().putFragment(outState, "any string you want as key", yourFragment);
    //or use code below if you use android.support.v4.app.Fragment 
    //getSupportFragmentManager().putFragment(outState, "any string you want as key", yourFragment);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    if (savedInstanceState != null) {
        //retrieve your fragment that saved from onSaveInstanceState()
        yourFragment = (YourFragment) getFragmentManager().getFragment(savedInstanceState, "any string you want as key");
        //or
        //yourFragment = (YourFragment) getSupportFragmentManager().getFragment(savedInstanceState, "any string you want as key");
    }
    else {
        //create your fragment if it is first time
        yourFragment = new YourFragment();
    }
}

答案 1 :(得分:1)

由于您的问题从一开始就有所不同,实际上您不需要每次都在onNewIntent内重新创建片段。 你可以这样做:

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    if ("some_action".equals(intent.getAction())) {
        //your action, in your case create and assign fragment

        //remove the action
        intent.setAction(null);
    }
}

答案 2 :(得分:0)

嗯,我想我的问题来自完全不同的东西。 MainActivity在从一系列活动返回时使用AlarmFragment创建新的onNewIntent(),以定义每个AlarmFragment的值。显然,最小化应用然后重新打开它每次都会调用onNewIntent(),因此我的解决方案是确保我实际上正在使用数据创建新的AlarmFragments。愚蠢的问题,愚蠢的解决方案