2016-06-23 5 views
6

Parcelableを実装するさまざまなアクティビティにオブジェクトを渡すと、私のアプリケーションに奇妙なエラーが発生しているようです(GitHub参照)。java.lang.RuntimeException:Parcel android.os.Parcel:不明な型コードをアンマーシャリングしていません

スタックオーバーフローに関するその他の質問と回答を確認しましたが、解決策を見つけることができませんでした。私は、例えば、答えhereを試してみた - ここでは参考のためにある:

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

私もwriteToParcelのメソッド呼び出しが順番になっていることを確認作りました。この問題についての他のほとんどの質問には答えがありません。

また、私は新しい問題を尋ねている理由は、自分のアプリでインターフェイスをどのように使用したかによって問題が発生したと考えているからです(後ほど説明します)。スタックオーバーフローに関する他の質問は、私の特定のシナリオに合っていません。

以下では、必要に応じてコードの詳細を調べるために、GitHub経由でコードへのリンクを提供しました。

私は( Parcelableを実装するオブジェクトを渡す) launch a new activityへ]ボタンをクリックし

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) 
... 

私は(も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); 

私がmTopicを渡すときに考慮すべき主要部分です。これは私が作成したTopicinterfaceです。

しかし、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ことクラス(オブジェクト):Courseである上記のコードの最後の行の一つで

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を通過見ることができ、オブジェクトを作成しました。

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(); 

私は、任意の変数がnullの場合writeToParcel(...)に渡されるときに表示するLog.d(...)を使用してログメッセージを追加し、適切にデビッドワッサーの方法を使用しましたこれを対応して。

ただし、同じエラーメッセージが表示されます。

+0

'Intent'に入れられている実際のクラスのパーセル化とアンパイリングに関するコードを投稿してください。 –

+0

@DavidWasser 'Intent'に入れられたクラスのコードを表示するための答えを更新しました(提供されているGitHubリンクを通して完全に見ることができます)。 –

答えて

17

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); 
} 
+1

ありがとう - これは私の問題を解決! –

+0

すべてが同じタイプの場合、値の順序が変更できます。私は意味する mEnglish = in.readString(); mAnswerPrefix = in.readString(); mAnswer = in.readString(); は、 として読み取ることができます。 dest.writeString(mAnswer); dest.writeString(mEnglish); dest.writeString(mAnswerPrefix); –

+1

@UsmanRanaいいえ。値の種類にかかわらず、正確に同じ順序で値を読み書きする必要があります。バイト配列とのシリアル化とデシリアライズを行います。 'Parcel'は' HashMap'ではありません。 –

関連する問題