使用具有唯一ID的片段时很少发生崩溃

时间:2014-02-03 23:49:51

标签: android android-fragments

我有一个非常不寻常的崩溃,可能每个月发生一次。似乎没有任何押韵或理由。这是一个大项目的一部分,因为我不确定问题究竟发生在哪里,我不确定要在哪里粘贴代码部分。所以我只会描述我在做什么,而且我认为可能会导致崩溃。

我有一个带有许多嵌套片段的活动,我用FragmentManager管理它。因为嵌套的片段可以是相同的类型,所以我必须给每个片段的根视图一个唯一的ID。应用程序在调用super.onResume时崩溃,并且该调用是我重载的onResume函数的第一行(因此我的代码永远不会有机会弄乱任何东西)。我认为由于唯一片段id而崩溃的原因是因为我在转移到唯一ID后开始出现此问题,并且崩溃始终引用了一个低数量的资源ID。

这个错误似乎是在框架本身中引发的,所以我不确定我能做些什么。有没有其他人遇到这个,并找到了解决方案吗?或者,有没有人知道你是否可以用try / catch块包围super.onResume?我不确定应用程序是否能够在那时恢复,并且似乎没有任何方法可以一致地重现此错误以便进行测试。

01-24 20:55:09.602 E/AndroidRuntime( 8156): FATAL EXCEPTION: main
01-24 20:55:09.602 E/AndroidRuntime( 8156): java.lang.RuntimeException: Unable to resume activity {github.daneren2005.dsub/github.daneren2005.dsub.activity.SubsonicFragmentActivity}: android.content.res.Resources$NotFoundException: Unable to find resource ID #0x2
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3014)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3055)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2392)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at android.app.ActivityThread.access$600(ActivityThread.java:151)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1331)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at android.os.Handler.dispatchMessage(Handler.java:99)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at android.os.Looper.loop(Looper.java:155)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at android.app.ActivityThread.main(ActivityThread.java:5454)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at java.lang.reflect.Method.invokeNative(Native Method)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at java.lang.reflect.Method.invoke(Method.java:511)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1029)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:796)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at dalvik.system.NativeStart.main(Native Method)
01-24 20:55:09.602 E/AndroidRuntime( 8156): Caused by: android.content.res.Resources$NotFoundException: Unable to find resource ID #0x2
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at android.content.res.Resources.getResourceName(Resources.java:1666)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:919)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1467)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at android.support.v4.app.FragmentActivity.onResume(FragmentActivity.java:445)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at github.daneren2005.dsub.activity.SubsonicActivity.onResume(SubsonicActivity.java:130)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at github.daneren2005.dsub.activity.SubsonicFragmentActivity.onResume(SubsonicFragmentActivity.java:250)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1266)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at android.app.Activity.performResume(Activity.java:5148)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2997)
01-24 20:55:09.602 E/AndroidRuntime( 8156):     ... 12 more
01-24 20:55:09.602 W/ActivityManager(  596):   Force finishing activity github.daneren2005.dsub/.activity.SubsonicFragmentActivity

编辑:添加了唯一ID生成。在onCreateView中,我使用rootView.setId(rootId):

    public SelectDirectoryFragment() {
        super();
        rootId = getNewId();
    }

    @Override
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        if(bundle != null) {
            int tmp = bundle.getInt(Constants.FRAGMENT_ID, -1);
            if(tmp > 0) {
                rootId = tmp;
            }
            entries = (List<MusicDirectory.Entry>) bundle.getSerializable(Constants.FRAGMENT_LIST);
            restoredInstance = true;
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(Constants.FRAGMENT_ID, rootId);
        outState.putSerializable(Constants.FRAGMENT_LIST, (Serializable) entries);
    }

    protected int getNewId() {
        for (;;) {
            final int result = nextGeneratedId.get();
            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
            int newValue = result + 1;
            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
            if (nextGeneratedId.compareAndSet(result, newValue)) {
                return result;
            }
        }
    }

1 个答案:

答案 0 :(得分:1)

检查片段或活动中您可能正在进行setText()调用的任何位置。您可能尝试将文本设置为整数的String.valueOf()值,但setText()也有一个带有整数资源值的重载(例如R.string) .my_string)。当我错误地做了类似下面的事情时,我已经看到了这次崩溃:

int myCount = doSomeCalculation();
textView.setText(myCount);

这将在内部尝试将myCount解析为资源(例如getString(myCount)),而不是将文本设置为myCount变量的字符串值。

编辑:等等,您如何在Fragment的根目录上设置此唯一ID?