Ich bekomme einen seltsamen Fehler in meiner App (siehe GitHub), die auftritt, wenn ich Objekte an verschiedene Aktivitäten übergeben, die Parcelable
implementieren.java.lang.RuntimeException: Paket android.os.Parcel: Unmarshalling unbekannter Typ Code
Ich habe andere Fragen und Antworten hier auf Stack Overflow überprüft, aber ich konnte keine Lösung finden. Ich habe die Antwort here versucht, zum Beispiel - hier ist es als Referenz:
-keepclassmembers class * implements android.os.Parcelable {
static ** CREATOR;
}
ich auch dafür gesorgt haben, dass die Methodenaufrufe in writeToParcel
in Ordnung sind. Die meisten anderen Fragen zu Stack Overflow zu diesem Thema haben keine Antworten.
Darüber hinaus ist der Grund, warum ich eine neue Frage stelle, weil ich denke, dass mein Problem verursacht wird, weil ich Schnittstellen in meiner App verwendet habe (ich werde später auf diesen Punkt erweitern). Andere Fragen zu Stack Overflow würden meinem speziellen Szenario nicht gerecht werden.
Im Folgenden habe ich über GitHub Links zum Code bereitgestellt, damit Sie bei Bedarf mehr Code untersuchen können.
Wenn ich auf eine Schaltfläche, um launch a new activity (vorbei an ein Objekt, das Parcelable
implementiert), there is a crash:
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 [email protected]: Unmarshalling unknown type code 6815860 at offset 200
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
...
Caused by: java.lang.RuntimeException: Parcel [email protected]: 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)
...
ich die oben erwähnte Aktivität nennen wie so (auch see 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);
Der Hauptteil zu betrachten ist, wenn ich mTopic
passiere. Dies ist eine Topic
interface, die ich erstellt habe.
jedoch die Topic
Schnittstelle erweitert Parcelable
und so die Objekte, die Topic
umfassen auch den Konstruktor, CREATOR
Feld, und die Methoden implementieren, die eine Klasse Parcelable
Implementierung normalerweise haben müssen.
Sie können die relevanten Klassen über die GitHub Links sehen, aber ich werde die relevanten Teile dieser Klassen unten zur Verfügung stellen. Hier ist die Topic
Schnittstelle:
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;
}
...
}
}
A-Klasse (Objekt), dass 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);
}
}
In einem der letzten Zeilen des Codes oben können Sie sehen, ich pass mCourse
, das ist ein Course
Objekt, das ich erstellt habe. Hier ist sie:
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);
}
}
ich etwas vermuten, hier kann das Problem verursacht, und ist der Grund, mein Szenario von denen in anderen Fragen unterscheiden.
Um ehrlich zu sein, ich bin nicht ganz sicher, was den Fehler verursacht sein kann, so Erklärungen und Anleitungen in Antworten sehr geschätzt werden würden.
bearbeiten:
Nach David Wasser ‚s Vorschläge, ich habe Teile meines Code aktualisiert wie folgt:
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();
Ich habe Protokollnachrichten hinzugefügt Log.d(...)
verwenden, wenn alle Variablen null sind, um zu sehen, wenn sie in writeToParcel(...)
und verwendet David Wasser geben wird ‚s Methode richtig geh damit um.
Ich bekomme immer noch die gleiche Fehlermeldung.
Geben Sie den Code für das Parzellieren und Unparceling für die tatsächlichen Klassen ein, die in den 'Intent' geschrieben werden. –
@DavidWasser Ich habe meine Antwort aktualisiert, um den Code für die Klassen anzuzeigen, die in den 'Intent' geschrieben wurden (sie können vollständig über die bereitgestellten GitHub-Links angezeigt werden). –