2016-06-23 5 views
6

Parcelable을 구현하는 다른 활동에 객체를 전달할 때 발생하는 이상한 오류가 내 응용 프로그램에서 발생하는 것 같습니다 (GitHub 참조).java.lang.RuntimeException : Parcel android.os.Parcel : 알 수없는 형식 코드를 비 정렬

스택 오버플로에 대한 다른 질문과 대답을 확인했지만 해결책을 찾지 못했습니다. 나는 예를 들어, 대답 here을 시도했습니다 - 여기 참조 용입니다 : 나는 또한 writeToParcel이 순서대로의 방법은 호출해야했습니다

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

. 이 문제에 대한 스택 오버플로에 대한 다른 질문에는 답변이 없습니다.

또한 새로운 질문을하는 이유는 내 응용 프로그램에서 인터페이스를 사용하는 방법 때문에 내 문제가 발생했다고 생각하기 때문입니다 (나중에이 지점에서 확장 할 예정입니다). 스택 오버플로에 대한 다른 질문은 내 특정 시나리오에 적합하지 않습니다.

다음은 필자는 GitHub를 통해 코드에 대한 링크를 제공 했으므로 필요한 경우 더 많은 코드를 탐색 할 수 있습니다.

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

I가 launch a new activity에 버튼 클릭

, there is a crash ( Parcelable를 구현하는 객체를 전달)

고려해야 할 주요 부분은 내가 mTopic을 전달할 때입니다. 이것은 내가 만든 Topicinterface입니다.

그러나, Topic 인터페이스는 Parcelable를 확장하고 그래서 Topic를 구현하는 객체는 생성자, CREATOR 필드 및 Parcelable를 구현하는 클래스가 정상적으로 있어야 할 방법을 포함한다.

관련 클래스는 GitHub 링크를 통해 볼 수 있지만 아래에서 해당 클래스의 관련 부분을 제공 할 것입니다.

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 것을 : 여기에 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); 
    } 

} 

, 당신은 내가 CoursemCourse을 통과 볼 수 있습니다 내가 만든 물건.

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

}

내가 여기서 뭔가를 의심 문제의 원인이 될 수 있으며, 내 시나리오는 다른 질문에 그 다른 이유이다 : 여기있다.


는 답변에 대한 설명과 안내가 많이 주시면 감사하겠습니다 그래서, 오류의 원인이 될 수있다 정확히 모르겠어요, 정직합니다.


편집 :

데이비드 WASSER의 제안 후, 난 그렇게처럼 내 코드의 일부를 업데이트 한 :

FlashCardActivity.java - onCreate(...) :

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

Course.java - writeToParcel(...) :

012 3,516,
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(); 

내가 writeToParcel(...) 전달하고 데이비드 WASSER의 방법을 사용하면 어떤 변수가 제대로을하는 경우는 null 있는지 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에 쓰는 두 번째 항목은 int이고 두 번째 항목은 Parcel이고 두 번째 항목은 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'이 아닙니다. –