Sembra che si verifichi uno strano errore nella mia app (vedere GitHub), che si verifica quando si passano oggetti a diverse attività che implementano Parcelable
.java.lang.RuntimeException: Parcel android.os.Parcel: codice sconosciuto codice sconosciuto
Ho controllato altre domande e risposte qui su Stack Overflow, ma non sono riuscito a trovare una soluzione. Ho provato la risposta here, per esempio - qui è per riferimento:
-keepclassmembers class * implements android.os.Parcelable {
static ** CREATOR;
}
Ho anche fatto in modo che il metodo chiama writeToParcel
sono in ordine. La maggior parte delle altre domande su Stack Overflow relative a questo problema non hanno risposte.
Inoltre, il motivo per cui sto facendo una nuova domanda è perché penso che il mio problema sia causato da come ho usato le interfacce nella mia app (mi dilungherò su questo punto in seguito). Altre domande su Stack Overflow non si adattano al mio particolare scenario.
Di seguito, ho fornito collegamenti al codice tramite GitHub, in modo che sia possibile esplorare più del codice, se necessario.
Quando scatto sopra un pulsante per launch a new activity (passaggio di un oggetto che implementa Parcelable
), 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)
...
io chiamo dell'attività citata in questo modo (anche 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);
La parte principale da considerare è quando passo mTopic
. Questo è un Topic
interface che ho creato.
Tuttavia, l'interfaccia Topic
estende Parcelable
e così gli oggetti che implementano Topic
includono anche il costruttore, CREATOR
campo, ei metodi che una classe che implementa Parcelable
normalmente dovrebbe avere.
È possibile visualizzare le classi rilevanti tramite i collegamenti GitHub, ma fornirò le parti pertinenti di queste classi di seguito. Qui è l'interfaccia 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;
}
...
}
}
una classe (oggetto) che 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 una delle ultime righe del codice di cui sopra, si può vedere che passo mCourse
, che è un Course
oggetto che ho creato. Eccolo:
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);
}
}
Ho il sospetto che qualcosa qui potrebbero essere la causa del problema, ed è il motivo per il mio scenario è diverso da quelli di altre questioni.
Per essere onesti, io non sono esattamente sicuro di quello che potrebbe essere causa l'errore, in modo da spiegazioni e guida in risposte sarebbe molto apprezzato.
Edit:
Dopo suggerimenti David Wasser s', ho aggiornato le parti del mio codice in questo modo:
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();
Ho aggiunto i messaggi di log utilizzando Log.d(...)
per vedere se tutte le variabili sono nulli quando viene passato in writeToParcel(...)
e utilizzato il metodo David Wasser s' correttamente gestire questo.
Ho ancora lo stesso messaggio di errore, tuttavia.
Inviare il codice relativo alla parcel e alla non assegnazione per le classi effettive immesse nell'intento. –
@DavidWasser Ho aggiornato la mia risposta per mostrare il codice per le classi inserite nell '"Intento" (possono essere visualizzate integralmente tramite i link GitHub forniti). –