2014-10-08 89 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