2012-04-09 14 views
64

मैं कक्षा जो पढ़ता है और से/एक पार्सल करने के लिए वस्तुओं की एक सरणी लिखते हैं निम्नलिखित हैं वस्तुओंपढ़ें और Parcelable की सरणियों लेखन

त्रुटि/एंड्रॉइड रनटाइम (5880): इसके कारण: java.lang.ClassCastException: [Landroid.os.Parcelable;

उपरोक्त कोड में क्या गलत है? ऑब्जेक्ट सरणी लिखते समय, क्या मुझे पहले सरणी को ArrayList में परिवर्तित करना चाहिए?

अद्यतन:

क्या यह ठीक है एक ArrayList के लिए एक वस्तु सरणी परिवर्तित और पार्सल में जोड़ने के लिए? उदाहरण के लिए, जब लेखन:

ArrayList<MyClass> tmpArrya = new ArrayList<MyClass>(mObjList.length); 
    for (int loopIndex=0;loopIndex != mObjList.length;loopIndex++) { 
     tmpArrya.add(mObjList[loopIndex]); 
    } 
    out.writeArray(tmpArrya.toArray()); 

जब पढ़ने:

final ArrayList<MyClass> tmpList = 
      in.readArrayList(com.myApp.MyClass.class.getClassLoader()); 
    mObjList= new MyClass[tmpList.size()]; 
    for (int loopIndex=0;loopIndex != tmpList.size();loopIndex++) { 
     mObjList[loopIndex] = tmpList.get(loopIndex); 
    } 

लेकिन अब मैं एक NullPointerException मिलता है। ऊपर दृष्टिकोण सही है? यह एनपीई क्यों फेंक रहा है?

+0

mcononversationMemberList का प्रकार क्या है? – Chetan

+0

मैंने सवाल अपडेट किया है, यह MyClass [] प्रकार का है। – User7723337

उत्तर

139

आप Parcel.writeTypedArray() पद्धति का उपयोग करके सरणी लिखने के लिए और यह Parcel.createTypedArray() विधि के साथ वापस पढ़ें, तो तरह की जरूरत है:

MyClass[] mObjList; 

public void writeToParcel(Parcel out) { 
    out.writeTypedArray(mObjList, 0); 
} 

private void readFromParcel(Parcel in) { 
    mObjList = in.createTypedArray(MyClass.CREATOR); 
} 

कारण आपको readParcelableArray()/writeParcelableArray() विधियों का उपयोग क्यों नहीं करना चाहिए readParcelableArray() वास्तव में परिणामस्वरूप Parcelable[] बनाता है। इसका मतलब है कि आप विधि का परिणाम MyClass[] पर नहीं डाल सकते हैं। इसके बजाय आपको परिणाम के समान लंबाई की MyClass सरणी बनाना होगा और परिणाम तत्व से प्रत्येक तत्व को MyClass सरणी में कॉपी करना होगा।

Parcelable[] parcelableArray = 
     parcel.readParcelableArray(MyClass.class.getClassLoader()); 
MyClass[] resultArray = null; 
if (parcelableArray != null) { 
    resultArray = Arrays.copyOf(parcelableArray, parcelableArray.length, MyClass[].class); 
} 
+1

चाहता हूं धन्यवाद, यह चाल है! इसे दस्तावेज़ीकरण में स्पष्ट किया जाना चाहिए क्योंकि विधि नामकरण इसे पार्ससेल योग्य सरणी की तरह ध्वनि बनाता है, जिसे लिखा जाना चाहिए, जब यह स्पष्ट रूप से अधिक कोड है। – Tom

+0

हां, विधि का नाम थोड़ा उलझन में है। जब मुझे इस समस्या का सामना करना पड़ा, तो इसे हल करने का एकमात्र तरीका एंड्रॉइड स्रोत पढ़ रहा था, इसलिए मैंने इस जवाब को लिखने का फैसला किया। – Michael

+3

वैसे, 'if (parcelableArray! = Null) {...} 'के भीतर बयानों को' resultArray = Arrays.copyOf (पार्सलएबलएरे, पार्ससेल योग्यअरे। लम्बाई, MyClass [] वर्ग) में सरलीकृत किया जा सकता है;' – CrimsonX

34

त्रुटि/एंड्रॉइड रनटाइम (5880): इसके कारण: java.lang.ClassCastException: [Landroid.os.Parcelable;

API के अनुसार, readParcelableArray विधि Parcelable सरणी (Parcelable []), जो केवल MyClass सरणी के लिए casted नहीं किया जा सकता (MyClass []) देता है।

लेकिन अब मुझे नल पॉइंटर अपवाद मिलता है।

विस्तृत अपवाद स्टैक ट्रेस के बिना सटीक कारण बताना मुश्किल है।


मान लीजिए आप बना दिया है MyClass ठीक से लागू करता है Parcelable, यह कैसे हम आम तौर पर/serialize के लिए क्या parcelable वस्तुओं की एक सरणी deserialize है:

public class ClassABC implements Parcelable { 

    private List<MyClass> mObjList; // MyClass should implement Parcelable properly 

    // ==================== Parcelable ==================== 
    public int describeContents() { 
    return 0; 
    } 

    public void writeToParcel(Parcel out, int flags) { 
    out.writeList(mObjList); 
    } 

    private ClassABC(Parcel in) { 
    mObjList = new ArrayList<MyClass>(); 
    in.readList(mObjList, getClass().getClassLoader()); 
    } 

    public static final Parcelable.Creator<ClassABC> CREATOR = new Parcelable.Creator<ClassABC>() { 
    public ClassABC createFromParcel(Parcel in) { 
     return new ClassABC(in); 
    } 
    public ClassABC[] newArray(int size) { 
     return new ClassABC[size]; 
    } 
    }; 

} 

आशा इस मदद करता है।

तुम भी निम्न विधियों का उपयोग कर सकते हैं:

public void writeToParcel(Parcel out, int flags) { 
     out.writeTypedList(mObjList); 
    } 

    private ClassABC(Parcel in) { 
     mObjList = new ArrayList<ClassABC>(); 
     in.readTypedList(mObjList, ClassABC.CREATOR); 
    } 
+5

यह 'getClass() के बजाय' MyClass.class.getClassLoader() 'नहीं होना चाहिए। GetClassLoader()'? क्योंकि मुझे लगता है कि क्लास लोडर का इस्तेमाल उस पारदर्शी वर्ग को खोजने के लिए किया जा रहा है जिसे हम पढ़ने की कोशिश कर रहे हैं। –

+0

बिल्कुल मुझे कक्षा एबीसी नहीं चाहिए, मैं MyClass – Srneczek

9

मुझे एक ही समस्या थी, और इसे इस तरह हल किया गया। मैं MyClass में एक सहायक विधि परिभाषित, MyClass की एक सरणी के लिए Parcelable की एक सरणी परिवर्तित करने के लिए वस्तुओं:

public static MyClass[] toMyObjects(Parcelable[] parcelables) { 
    MyClass[] objects = new MyClass[parcelables.length]; 
    System.arraycopy(parcelables, 0, objects, 0, parcelables.length); 
    return objects; 
} 

जब भी मैं MyClass वस्तुओं, जैसे की एक parcelable सरणी पढ़ने की जरूरत है

MyClass[] objects = MyClass.toMyObjects(getIntent().getParcelableArrayExtra("objects")); 

संपादित:

public static MyClass[] toMyObjects(Parcelable[] parcelables) { 
    if (parcelables == null) 
     return null; 
    return Arrays.copyOf(parcelables, parcelables.length, MyClass[].class); 
} 
+0

मुझे लगता है कि मैं अब इस जवाब को बुकमार्क कर दूंगा। अब कुछ बार हो गया है कि मैं इस जादुई कोड की प्रतिलिपि बनाने के लिए वापस आया हूं: डी – Sufian

+0

@ जॉर्जियो बार्चीसी, एंड्रॉइड स्टूडियो में एक चेतावनी प्रदर्शित हो रही है: स्रोत पार्सेलबल है और गंतव्य MyClass है, लेकिन एप्लिकेशन अपेक्षित काम करता है। कैसे ? – kaushik

+0

@ कौशिक, आपकी टिप्पणी के लिए धन्यवाद, मैंने अपना जवाब संपादित कर लिया है, कृपया "toMyObject" फ़ंक्शन का नया संस्करण देखें। –

2

आप सरणी लिखने की ज़रूरत: यहाँ एक ही समारोह के एक अद्यतन संस्करण है कि मैं अभी हाल ही में उपयोग कर रहा हूँ, चेतावनी संकलन से बचने के लिए है एक इरादे से Parcel.writeTypedArray() पद्धति का उपयोग करके और इसे वापस पढ़ा Parcel.readTypedArray() विधि के साथ है, तो जैसे:

MyClass[] mObjArray; 

public void writeToParcel(Parcel out, int flags) { 
    out.writeInt(mObjArray.length); 
    out.writeTypedArray(mObjArray, flags); 
} 

protected MyClass(Parcel in) { 
    int size = in.readInt(); 
    mObjArray = new MyClass[size]; 
    in.readTypedArray(mObjArray, MyClass.CREATOR); 
} 

सूचियों के लिए, आप के लिए क्या कर सकते हैं llowing:

ArrayList<MyClass> mObjList; 

    public void writeToParcel(Parcel out, int flags) { 
     out.writeTypedList(mObjList); 
    } 

    protected MyClass(Parcel in) { 
     mObjList = new ArrayList<>(); //non-null reference is required 
     in.readTypedList(mObjList, MyClass.CREATOR); 
    } 
संबंधित मुद्दे