BadParcelableException:在反序列化时找不到ClassNotFoundException:android.support.v4.app.FragmentManagerState

15

三天前我迁移到了SDK Android 27.1.0,但出现了像这样的一些崩溃,我不明白为什么。它目前出现在Android 8和6上。

BadParcelableException ClassNotFoundException when unmarshalling: android.support.v4.app.FragmentManagerState android.support.v4.app.Fragment.setUserVisibleHint

android.os.Parcel.readParcelableCreator (Parcel.java:2916)
android.os.Parcel.readParcelable (Parcel.java:2842)
android.os.Parcel.readValue (Parcel.java:2745)
android.os.Parcel.readArrayMapInternal (Parcel.java:3114)
android.os.BaseBundle.initializeFromParcelLocked (BaseBundle.java:273)
android.os.BaseBundle.unparcel (BaseBundle.java:226)
android.os.BaseBundle.putBoolean (BaseBundle.java:532)
arrow_right
android.support.v4.app.Fragment.setUserVisibleHint (Fragment.java:960)
android.support.v4.app.FragmentStatePagerAdapter.instantiateItem (FragmentStatePagerAdapter.java:121)
android.support.v4.view.ViewPager.addNewItem (ViewPager.java:1004)
android.support.v4.view.ViewPager.populate (ViewPager.java:1218)
android.support.v4.view.ViewPager.populate (ViewPager.java:1086)
android.support.v4.view.ViewPager$3.run (ViewPager.java:267)
android.view.Choreographer$CallbackRecord.run (Choreographer.java:911)
android.view.Choreographer.doCallbacks (Choreographer.java:723)
android.view.Choreographer.doFrame (Choreographer.java:655)
android.view.Choreographer$FrameDisplayEventReceiver.run (Choreographer.java:897)
android.os.Handler.handleCallback (Handler.java:790)
android.os.Handler.dispatchMessage (Handler.java:99)
android.os.Looper.loop (Looper.java:164)
android.app.ActivityThread.main (ActivityThread.java:6494)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:438)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:807)

这是我的适配器:

public abstract class CalendarPagerAdapter extends FragmentStatePagerAdapter {

    private static final String TAG = LogUtils.makeLogTag(CalendarPagerAdapter.class);

    protected DateTime mDateTime;
    private final int mCount;
    protected int mTodayPosition;

    public static class CalendarContext {
        public int mRange; // range = nb of days supported
        public int mTodayPosition; // Today index in this area
        public int mCurrentWeek; // Week number of today
        public DateTime mFrom, mTo; // Compute from and to datetimes
        public boolean mIsSundayFirstDay;

        public CalendarContext(int area, int todayPosition, DateTime from, DateTime to,
                               int currentWeek, boolean isSundayFirstDay) {
            mRange = area;
            mTodayPosition = todayPosition;
            mFrom = from;
            mTo = to;
            mCurrentWeek = currentWeek;
            mIsSundayFirstDay = isSundayFirstDay;
        }
    }

    public static CalendarContext computeAreaAndTodayPosition(int initialArea, int initialTodayPosition) {
        // Compute min / max dates from now
        DateTime from = new DateTime().minusDays(initialArea - initialTodayPosition).dayOfWeek().withMinimumValue();
        DateTime to = new DateTime().plusDays(initialTodayPosition).dayOfWeek().withMaximumValue();

        boolean isSundayFirstDay = false;
        Calendar calendar = Calendar.getInstance(CompatUtils.getLocale(false));
        if (calendar.getFirstDayOfWeek() == Calendar.SUNDAY) {
            isSundayFirstDay = true;
            from = from.minusDays(1);
            to = to.minusDays(1);
        }

        LogUtils.LOGD("XXXX", "from dt=" + from.toString());
        LogUtils.LOGD("XXXX", "to dt=" + to.toString());

        // Compute nb days area supported
        int daysRange = daysBetween(from, to).getDays() + 1;
        LogUtils.LOGD("XXXX", "daysRange=" + daysRange);

        // Compute today position
        int todayPosition = daysBetween(from, DateTime.now().withTimeAtStartOfDay()).getDays() + 1;
        LogUtils.LOGD("XXXX", "todayPosition=" + todayPosition);

        int currentWeek = DateTime.now().getWeekOfWeekyear() - from.getWeekOfWeekyear();
        LogUtils.LOGD("XXXX", "currentWeek=" + currentWeek);

        return new CalendarContext(daysRange, todayPosition, from, to, currentWeek, isSundayFirstDay);
    }

    public CalendarPagerAdapter(FragmentManager mgr, int count, int todayPosition) {
        super(mgr);
        mDateTime = DateTime.now();
        mCount = count;
        mTodayPosition = todayPosition;
    }

    @Override
    public int getCount() {
        return mCount;
    }

    public boolean isTodayPosition(int position) {
        return computeDifferenceDays(position) == 0;
    }

    public boolean isPastPosition(int position) {
        return computeDifferenceDays(position) < 0;
    }

    public boolean isFuturPosition(int position) {
        return computeDifferenceDays(position) > 0;
    }

    protected int computeDifferenceDays(int position) {
        return position - getCalendarTodayPosition();
    }

    public long convertPositionToMs(int position) {
        return convertPositionToMs(mDateTime, position);
    }

    public long convertMinPositionToMs() {
        return convertPositionToMs(mDateTime, 0);
    }

    public long convertMaxPositionToMs() {
        return convertPositionToMs(mDateTime, mCount - 1);
    }

    public String convertPositionToDate(int position) {
        return TimeUnits.dateTimeToDateServer(new DateTime(convertPositionToMs(position)));
    }

    public long convertPositionToMs(DateTime datime, int position) {
        int dayNum = computeDifferenceDays(position);
        if (dayNum < 0)
            return datime.minusDays(Math.abs(dayNum)).getMillis();
        else if (dayNum > 0)
            return datime.plusDays(Math.abs(dayNum)).getMillis();
        else
            return datime.getMillis();
    }

    public int convertMsToPosition(long millis) {
        DateTime dtReceived = new DateTime(millis).withTimeAtStartOfDay();
        return convertDateTimeToPosition(dtReceived);
    }

    public int convertDateTimeToPosition(DateTime dtReceived) {
        DateTime now = DateTime.now().withTimeAtStartOfDay();
        int nbDays = daysBetween(now, dtReceived).getDays();
        return getCalendarTodayPosition() + nbDays;
    }

    public int getCalendarTodayPosition() {
        return mTodayPosition;
    }

    public void shiftWithOffset(WeekDatePicker weekDatePicker, TextView weekDatePickerDayTextView,
                                DateTime currentSelectedDate, int offset) {
        if (offset < 0 && mTodayPosition > 0) mTodayPosition += offset;
        mDateTime = DateTime.now();
        weekDatePicker.refreshTodayPosition();
        weekDatePickerDayTextView.setText(TimeUnits.dateTimeToString(
                currentSelectedDate, true, true, true, true, true));
    }
}

大家有没有解决这个问题的想法?

非常感谢!


你能分享一下你的代码吗? - Mohammod Hossain
你在模型中使用了可解析或序列化吗? - Mohammod Hossain
通常发生这种情况是因为库版本不匹配。 - KKSINGLA
请检查您的模型类,如果您已经在模型/POJO类中实现了Parcelable,请交叉检查是否有任何错误。 - Akshay
如果你正在使用Fragment Adapter,我建议你分享一下你的代码。 - Abdul Kawee
显示剩余7条评论
2个回答

8

@XJIOP说的是正确的,我在我的生产环境中也遇到了同样的问题,但我无法找到崩溃原因,我按照@XJIOP的方法产生了错误,并通过更新压缩版本从appcompat 27.1.0升级到27.1.1来解决了此问题。

由于我使用了proguard,所以我还向我的proguard添加了以下一行代码:

如果您的生产版本使用了proguard,则将以下一行代码添加到proguard中,否则请忽略:

-keepnames class * implements android.os.Parcelable {
    public static final ** CREATOR;
}

添加pro guard代码行并更新紧凑版库后,我能够解决问题并且这个错误在我更新的生产版本中没有再次报告。希望这可以帮助其他人。


谢谢。Proguard设置帮助我解决了另一个类似的问题。 - hgoebl

6

更新 Android 库至 27.1.0 后出现相同问题。

我的 viewPager 有 3 个选项卡,如果我选择第一个或最后一个选项卡,那么在失去活动并返回 viewPager 后选择另一个选项卡就会导致崩溃。

测试 2 个选项卡没有崩溃。

我的解决方法是

viewPager.setOffscreenPageLimit(2);

并且崩溃已经消失了

编辑

升级到27.1.1已解决问题


2
我在这里看到一个错误报告:https://issuetracker.google.com/issues/74130311。你们能否添加一些内容,以便他们可以提高优先级。 - j2emanue

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接