java.lang.RuntimeException: Посылка android.os.Parcel: Unmarshalling неизвестный код типа

Кажется, я получаю странную ошибку в моем приложении (см.GitHub), что происходит, когда я передаю объекты различным действиям, которые реализуютParcelable.

Я проверил другие вопросы и ответы здесь, на переполнение стека, но я не смог найти решение. Я попробовал ответВотНапример, вот оно для справки:

-keepclassmembers class * implements android.os.Parcelable {
    static ** CREATOR;
}

Я также убедился, что метод вызывает вwriteToParcel в порядке. На большинство других вопросов по переполнению стека об этой проблеме нет ответов.

Более того, причина, по которой я задаю новый вопрос, заключается в том, что я думаю, что моя проблема вызвана тем, как я использовал интерфейсы в своем приложении (я подробно остановлюсь на этом позже). Другие вопросы по переполнению стека не подошли бы для моего конкретного сценария.

Далее я предоставил ссылки на код через GitHub, чтобы вы могли изучить больше кода при необходимости.

Когда я нажимаю на кнопку, чтобыначать новую деятельность (передача объекта, который реализуетParcelable),есть авария:

Process: com.satsuware.flashcards, PID: 4664
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.satsuware.flashcards/com.satsumasoftware.flashcards.ui.FlashCardActivity}: java.lang.RuntimeException: Parcel android.os.Parcel@d2219e4: Unmarshalling unknown type code 6815860 at offset 200
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
    ...
 Caused by: java.lang.RuntimeException: Parcel android.os.Parcel@d2219e4: Unmarshalling unknown type code 6815860 at offset 200
at android.os.Parcel.readValue(Parcel.java:2319)
at android.os.Parcel.readListInternal(Parcel.java:2633)
at android.os.Parcel.readArrayList(Parcel.java:1914)
at android.os.Parcel.readValue(Parcel.java:2264)
at android.os.Parcel.readArrayMapInternal(Parcel.java:2592)
at android.os.BaseBundle.unparcel(BaseBundle.java:221)
at android.os.Bundle.getParcelable(Bundle.java:786)
at android.content.Intent.getParcelableExtra(Intent.java:5377)
at com.satsumasoftware.flashcards.ui.FlashCardActivity.onCreate(FlashCardActivity.java:71)
at android.app.Activity.performCreate(Activity.java:6237)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
...

Я называю вышеупомянутую деятельность как так (такжеувидеть GitHub):

Intent intent = new Intent(TopicDetailActivity.this, FlashCardActivity.class);
intent.putExtra(FlashCardActivity.EXTRA_TOPIC, mTopic);
intent.putExtra(FlashCardActivity.EXTRA_NUM_CARDS, mSelectedNumCards);
intent.putExtra(FlashCardActivity.EXTRA_CARD_LIST, mFilteredCards);
startActivity(intent);

Основная часть, чтобы рассмотреть, когда я прохожуmTopic, ЭтоTopic интерфейс что я создал.

Тем не менееTopic интерфейс расширяетсяParcelable и поэтому объекты, которые реализуютTopic также включить конструктор,CREATOR поле и методы, реализующие классParcelable обычно должен был бы иметь.

Вы можете просмотреть соответствующие классы по ссылкам GitHub, но я предоставлю соответствующие части этих классов ниже. ЗдесьTopic интерфейс:

public interface Topic extends Parcelable {

    int getId();

    String getIdentifier();

    String getName();

    Course getCourse();


    ArrayList<FlashCard> getFlashCards(Context context);


    class FlashCardsRetriever {

        public static ArrayList<FlashCard> filterStandardCards(ArrayList<FlashCard> flashCards, @StandardFlashCard.ContentType int contentType) {
            ArrayList<FlashCard> filteredCards = new ArrayList<>();
            for (FlashCard flashCard : flashCards) {
                boolean isPaper2 = ((StandardFlashCard) flashCard).isPaper2();
                boolean condition;
                switch (contentType) {
                    case StandardFlashCard.PAPER_1:
                        condition = !isPaper2;
                        break;
                    case StandardFlashCard.PAPER_2:
                        condition = isPaper2;
                        break;
                    case StandardFlashCard.ALL:
                        condition = true;
                        break;
                    default:
                        throw new IllegalArgumentException("content type '" + contentType + "' is invalid");
                }
                if (condition) filteredCards.add(flashCard);
            }
            return filteredCards;
        }

        ...
    }

}

Класс (объект), которыйimplements Topic:

public class CourseTopic implements Topic {

    ...

    public CourseTopic(int id, String identifier, String name, Course course) {
        ...
    }

    @Override
    public int getId() {
        return mId;
    }

    @Override
    public String getIdentifier() {
        return mIdentifier;
    }

    ...


    protected CourseTopic(Parcel in) {
        mId = in.readInt();
        mIdentifier = in.readString();
        mName = in.readString();
        mCourse = in.readParcelable(Course.class.getClassLoader());
    }

    public static final Parcelable.Creator<CourseTopic> CREATOR = new Parcelable.Creator<CourseTopic>() {
        @Override
        public CourseTopic createFromParcel(Parcel in) {
            return new CourseTopic(in);
        }

        @Override
        public CourseTopic[] newArray(int size) {
            return new CourseTopic[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mId);
        dest.writeString(mIdentifier);
        dest.writeString(mName);
        dest.writeParcelable(mCourse, flags);
    }

}

В одной из последних строк приведенного выше кода вы можете увидеть, как я передаюmCourse, который являетсяCourse объект, который я создал. Вот:

public class Course implements Parcelable {

    ...

    public Course(String subject, String examBoard, @FlashCard.CourseType String courseType,
              String revisionGuide) {
        ...
    }


    public String getSubjectIdentifier() {
        return mSubjectIdentifier;
    }

    public String getExamBoardIdentifier() {
        return mBoardIdentifier;
    }

    public ArrayList<Topic> getTopics(Context context) {
        ArrayList<Topic> topics = new ArrayList<>();
        String filename = mSubjectIdentifier + "_" + mBoardIdentifier + "_topics.csv";
        CsvParser parser = CsvUtils.getMyParser();
        try {
            List<String[]> allRows = parser.parseAll(context.getAssets().open(filename));
            for (String[] line : allRows) {
                int id = Integer.parseInt(line[0]);
                topics.add(new CourseTopic(id, line[1], line[2], this));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return topics;
    }

    ...


    protected Course(Parcel in) {
        mSubjectIdentifier = in.readString();
        mBoardIdentifier = in.readString();
        mCourseType = in.readString();
        mRevisionGuide = in.readString();
    }

    public static final Creator<Course> CREATOR = new Creator<Course>() {
        @Override
        public Course createFromParcel(Parcel in) {
            return new Course(in);
        }

        @Override
        public Course[] newArray(int size) {
            return new Course[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mSubjectIdentifier);
        dest.writeString(mBoardIdentifier);
        dest.writeString(mCourseType);
        dest.writeString(mRevisionGuide);
    }

}

Я подозреваю, что что-то здесь может быть причиной проблемы, и это причина, по которой мой сценарий отличается от других вопросов.

Если честно, я не совсем уверен, что может быть причиной ошибки, поэтому объяснения и рекомендации в ответах будут высоко оценены.

редактировать:

ПослеДэвид ВассерВ предложениях я обновил части своего кода следующим образом:

FlashCardActivity.java -onCreate(...):

Bundle extras = getIntent().getExtras();
extras.setClassLoader(Topic.class.getClassLoader());
mTopic = extras.getParcelable(EXTRA_TOPIC);

Course.java -writeToParcel(...):

dest.writeString(mSubjectIdentifier);
dest.writeString(mBoardIdentifier);
dest.writeString(mCourseType);
dest.writeInt(mRevisionGuide == null ? 0 : 1);
if (mRevisionGuide != null) dest.writeString(mRevisionGuide);

Course.java -Course(Parcel in):

mSubjectIdentifier = in.readString();
mBoardIdentifier = in.readString();
mCourseType = in.readString();
if (in.readInt() != 0) mRevisionGuide = in.readString();

Я добавил сообщения журнала, используяLog.d(...) чтобы увидеть, если какие-либо переменные являются нулевыми при передаче вwriteToParcel(...) и использовалДэвид Вассерспособ правильно с этим справиться.

Я все еще получаю то же сообщение об ошибке, однако.

Ответы на вопрос(1)

Ваш ответ на вопрос