android - पार्ससेल योग्य वस्तुओं के सरणी पढ़ें और लिखना




parcelable (3)

मेरे पास निम्न वर्ग है जो ऑब्जेक्ट्स की एक सरणी को पार्सल से पढ़ता है और लिखता है:

class ClassABC extends Parcelable {
    MyClass[] mObjList;

    private void readFromParcel(Parcel in) {
        mObjList = (MyClass[]) in.readParcelableArray(
                com.myApp.MyClass.class.getClassLoader()));
    }

    public void writeToParcel(Parcel out, int arg1) {
        out.writeParcelableArray(mObjList, 0);
    }

    private ClassABC(Parcel in) {
        readFromParcel(in);
    }

    public int describeContents() {
        return 0;
    }

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

उपरोक्त कोड में पढ़ने के दौरान readParcelableArray :

ERROR / AndroidRuntime (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 मिलता है। ऊपर दृष्टिकोण सही है? यह एनपीई क्यों फेंक रहा है?


ERROR / AndroidRuntime (5880): इसके कारण: java.lang.ClassCastException: [Landroid.os.Parcelable;

API अनुसार, readParcelableArray विधि पार्ससेल योग्य सरणी (पार्ससेलबल []) देता है, जिसे आसानी से MyClass array (MyClass []) में नहीं डाला जा सकता है।

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

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

मान लीजिए कि आपने MyClass को पार्सिलबल को सही तरीके से लागू किया है, इस प्रकार हम आमतौर पर पार्सल करने योग्य ऑब्जेक्ट्स की सरणी को क्रमबद्ध / 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);
  }

आपको Parcel.writeTypedArray() विधि का उपयोग करके सरणी 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);
}

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

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

जब भी मुझे MyClass ऑब्जेक्ट्स की एक पार्ससेल योग्य सरणी पढ़ने की आवश्यकता होती है, उदाहरण के लिए एक इरादे से:

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




parcelable