アプリで奇妙なエラーが発生しているようです( GitHub を参照)。これは、Parcelable
を実装するさまざまなアクティビティにオブジェクトを渡すと発生します。
Stack Overflowで他の質問と回答を確認しましたが、解決策を見つけることができませんでした。私は答えを試してみました ここ 、たとえば-ここでそれは参照用です:
_-keepclassmembers class * implements Android.os.Parcelable {
static ** CREATOR;
}
_
writeToParcel
のメソッド呼び出しが正しいことも確認しました。この問題に関するスタックオーバーフローに関する他のほとんどの質問には回答がありません。
さらに、私が新しい質問をするのは、自分の問題は自分のアプリでインターフェイスをどのように使用したかに起因していると思います(この点については後で詳しく説明します)。 Stack Overflowに関する他の質問は、私の特定のシナリオには適していません。
以下では、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
interface です。
ただし、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);
}
}
_
上記のコードの最後の行の1つに、作成した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);
}
_
}
ここで何かが問題を引き起こしているのではないかと思うので、私のシナリオが他の質問のシナリオと異なるのはこのためです。
正直なところ、何が原因でエラーが発生するのか正確にはわからないので、説明や回答のガイダンスをいただければ幸いです。
編集:
David Wasserの提案の後、次のようにコードの一部を更新しました:
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(...)
で渡されたときに変数がnullであるかどうかを確認するためにwriteToParcel(...)
を使用してログメッセージを追加し、David Wasserを使用しましたこれを適切に処理するメソッド。
ただし、同じエラーメッセージが引き続き表示されます。
あなたの問題はLanguagesFlashCard
にあります。パーセル/アンパーセルメソッドは次のとおりです。
protected LanguagesFlashCard(Parcel in) {
mId = in.readInt();
mEnglish = in.readString();
mAnswerPrefix = in.readString();
mAnswer = in.readString();
mTier = in.readInt();
mTopic = in.readParcelable(Topic.class.getClassLoader());
}
ご覧のとおり、それらは一致しません。 Parcel
に書き込む2番目の項目はint
であり、Parcel
から読み取る2番目の項目はString
です。
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mId);
dest.writeInt(mTier);
dest.writeString(mEnglish);
dest.writeString(mAnswerPrefix);
dest.writeString(mAnswer);
dest.writeParcelable(mTopic, flags);
}