2014-10-08 79 views
0

我看不到錯誤,我有這個問題已經很久了...我的parcelable類崩潰,如果它被重新創建,但我找不到問題.. 。ArrayIndexOutOfBoundsException拋出一組枚舉時

  • 我檢查了寫入/讀取數據的順序。
  • 我檢查我用(直讀/寫VS我俗空保存功能)

標誌着我在第一個代碼塊的行創建下列異常的功能:java.lang.ArrayIndexOutOfBoundsException: length=5; index=5

短碼

private Set<ContactType> mMatchesDataLoaded = new HashSet<ContactType>(); 

存儲設置

dest.writeInt(mMatchesDataLoaded.size()); 
Iterator<ContactType> it = mMatchesDataLoaded.iterator(); 
while (it.hasNext()) 
    dest.writeInt(it.next().ordinal()); 

讀集

int count = source.readInt(); 
for (int i = 0; i < count; i++) 
// --------------------------------------------------------------------------- 
// next line produces EXCEPTION!!! java.lang.ArrayIndexOutOfBoundsException: length=5; index=5 
// --------------------------------------------------------------------------- 
    mMatchesDataLoaded.add(ContactType.values()[source.readInt()]); 

全碼

我看不出任何問題,或者更確切地說,問題出在哪裏?

public class ContactPhone implements Parcelable 
{ 
    public static enum ContactType 
    { 
     WhatsApp, 
     Viber, 
     GooglePlus, 
     Twitter, 
     Instagram 
    } 

    private boolean mIsUserProfile = false; 
    private boolean mHasImage; 
    private int mId; 
    private long mRawId; 
    private String mName = null; 
    private List<PhoneNumber> mNumbers = new ArrayList<PhoneNumber>(); 
    private DBPhoneContact mDBContact = null; 

    private Set<ContactType> mMatchesDataLoaded = new HashSet<ContactType>(); 
    private HashMap<ContactType, List<BaseMatchContact>> mMatchesData = new HashMap<ContactType, List<BaseMatchContact>>(); 

    // ---------------------- 
    // Parcelable 
    // ---------------------- 

    @Override 
    public void writeToParcel(Parcel dest, int flags) 
    { 
     ParcelBundleUtils.writeBoolean(dest, mIsUserProfile); 
     ParcelBundleUtils.writeBoolean(dest, mHasImage); 
     ParcelBundleUtils.writeIntegerNullSafe(dest, mId); 
     ParcelBundleUtils.writeLongNullSafe(dest, mRawId); 
     ParcelBundleUtils.writeStringNullSafe(dest, mName); 
     dest.writeList(mNumbers); 

     ParcelBundleUtils.writeLongNullSafe(dest, mDBContact != null ? mDBContact.getId() : null); 

     // save set 
     dest.writeInt(mMatchesDataLoaded.size()); 
     Iterator<ContactType> it = mMatchesDataLoaded.iterator(); 
     while (it.hasNext()) 
      dest.writeInt(it.next().ordinal()); 

     // save HashMap 
     dest.writeInt(mMatchesData.size()); 
     for (Map.Entry<ContactType, List<BaseMatchContact>> entry : mMatchesData.entrySet()) 
     { 
      dest.writeInt(entry.getKey().ordinal()); 
      dest.writeInt(entry.getValue().size()); 
      for (int i = 0; i < entry.getValue().size(); i++) 
       dest.writeParcelable(entry.getValue().get(i), 0); 
     } 
    } 

    public void readFromParcel(Parcel source) 
    { 
     mIsUserProfile = ParcelBundleUtils.readBoolean(source); 
     mHasImage = ParcelBundleUtils.readBoolean(source); 
     mId = ParcelBundleUtils.readIntegerNullSafe(source); 
     mRawId = ParcelBundleUtils.readLongNullSafe(source); 
     mName = ParcelBundleUtils.readStringNullSafe(source); 
     source.readList(mNumbers, PhoneNumber.class.getClassLoader()); 

     Long id = ParcelBundleUtils.readLongNullSafe(source); 
     mDBContact = null; 
     if (id != null) 
      mDBContact = MainApp.getDS().getDBPhoneContactDao().load(id); 

     // read set 
     int count = source.readInt(); 
     for (int i = 0; i < count; i++) 
// --------------------------------------------------------------------------- 
// next line produces EXCEPTION!!! java.lang.ArrayIndexOutOfBoundsException: length=5; index=5 
// --------------------------------------------------------------------------- 
      mMatchesDataLoaded.add(ContactType.values()[source.readInt()]); 

     // read HashMap 
     count = source.readInt(); 
     for (int i = 0; i < count; i++) 
     { 
      ContactType type = ContactType.values()[source.readInt()]; 
      Class<?> clazz = BaseDef.getMatchClass(type); 
      // L.d(this, "Classloader: " + clazz.getName() + " type: " + type.name()); 
      int size = source.readInt(); 
      List<BaseMatchContact> list = new ArrayList<BaseMatchContact>(); 
      for (int j = 0; j < size; j++) 
       list.add((BaseMatchContact) source.readParcelable(clazz.getClassLoader())); 
      mMatchesData.put(type, list); 
     } 
    } 
} 

PhoneNumber類實現parcelable,很簡單,閱讀/寫得像以下:

@Override 
public void writeToParcel(Parcel dest, int flags) 
{ 
    ParcelBundleUtils.writeStringNullSafe(dest, mName); 
    ParcelBundleUtils.writeStringNullSafe(dest, mNormNumber); 
    ParcelBundleUtils.writeStringNullSafe(dest, mNumber); 
} 

public void readFromParcel(Parcel source) 
{ 
    mName = ParcelBundleUtils.readStringNullSafe(source); 
    mNormNumber = ParcelBundleUtils.readStringNullSafe(source); 
    mNumber = ParcelBundleUtils.readStringNullSafe(source); 
} 

這裏是我的輔助功能:

public static void writeBoolean(Parcel p, boolean b) 
{ 
    p.writeByte((byte) (b ? 1 : 0)); 
} 

public static boolean readBoolean(Parcel p) 
{ 
    return p.readByte() == 1; 
} 

public static void writeStringNullSafe(Parcel p, String s) 
{ 
    p.writeByte((byte) (s != null ? 1 : 0)); 
    if (s != null) 
     p.writeString(s); 
} 

public static void writeIntegerNullSafe(Parcel p, Integer i) 
{ 
    p.writeByte((byte) (i != null ? 1 : 0)); 
    if (i != null) 
     p.writeInt(i); 
} 

public static void writeLongNullSafe(Parcel p, Long l) 
{ 
    p.writeByte((byte) (l != null ? 1 : 0)); 
    if (l != null) 
     p.writeLong(l); 
} 

public static void writeDoubleNullSafe(Parcel p, Double d) 
{ 
    p.writeByte((byte) (d != null ? 1 : 0)); 
    if (d != null) 
     p.writeDouble(d); 
} 

public static void writeParcelableNullSafe(Parcel p, Parcelable d, int flags) 
{ 
    p.writeByte((byte) (d != null ? 1 : 0)); 
    if (d != null) 
     p.writeParcelable(d, flags); 
} 

public static String readStringNullSafe(Parcel p) 
{ 
    boolean isPresent = p.readByte() == 1; 
    return isPresent ? p.readString() : null; 
} 

public static Integer readIntegerNullSafe(Parcel p) 
{ 
    boolean isPresent = p.readByte() == 1; 
    return isPresent ? p.readInt() : null; 
} 

public static Long readLongNullSafe(Parcel p) 
{ 
    boolean isPresent = p.readByte() == 1; 
    return isPresent ? p.readLong() : null; 
} 

public static Double readDoubleNullSafe(Parcel p) 
{ 
    boolean isPresent = p.readByte() == 1; 
    return isPresent ? p.readDouble() : null; 
} 

@SuppressWarnings("unchecked") 
public static <T extends Parcelable> T readParcelableNullSafe(Parcel p, ClassLoader classLoader) 
{ 
    boolean isPresent = p.readByte() == 1; 
    return isPresent ? (T) p.readParcelable(classLoader) : null; 
} 

回答

0

ContactType包含5個值,從索引0到索引4.您試圖訪問該指數5,這不存在。

mMatchesDataLoaded.add(ContactType.values()[source.readInt()]); 

source.readInt()給你一個5,試圖弄清楚,用debug,爲什麼它包含這個值。

我的猜測是,writeToParcel寫這個5,儘量檢查mMatchesDataLoaded這可能包含一些額外的不利數據。

+0

實際上,那是相當的apperent ......它崩潰,我不能重現的情況下。所以我不知道,如何來5在那裏。當我查看代碼時,它不應該在那裏...... – prom85 2014-10-08 09:22:50

+0

您無法重現該案例,因此問題來自您的某個用戶? – ToYonos 2014-10-08 09:29:51

+0

究竟...一些特殊體質導致上述異常... – prom85 2014-10-08 09:45:03

1
int count = source.readInt(); // index is raised + 1 
for (int i = 0; i < count; i++) 
    mMatchesDataLoaded.add(ContactType.values()[source.readInt()]); // index is raised by 1, starting with 1! 

你循環從0到4,但source.readInt()已經被調用一次,所以你總叫它5倍。

+0

readInt()的工作方式類似於迭代器......它將內部指針移動到下一個位置......所以這是正確的。而且我不會從一個循環到4個循環,而是從0循環到0到4之間的某個值... – prom85 2014-10-08 09:47:14

+0

啊,你讓我找到了解決方案! – dube 2014-10-08 09:51:40

+0

更好的建議,現在,還是錯的:看我的保存功能,我設定的數據寫入之前寫的套入地塊的大小...我反正需要它來確定,有多少條目可以從束讀 – prom85 2014-10-08 09:58:31

相關問題