在 Android 中 parcelable.readArrayList() 中使用 ClassLoader

Use of ClassLoader in parcelable.readArrayList() in Android

我有一个名为 FilterData 的 Class,它实现了 Parcelable。我有一个成员变量private ArrayList<String> listPropertyType; 在我的class、parcel.readArrayList(null)中实现parcelable接口时,参数显示为ClassLoader object。使用此成员变量,FilterData class 将按预期工作。但是我想实现一个将 ClassLoader object 传递给 readArrayList() 方法的场景。

所以我从关于 public ArrayList readArrayList (ClassLoader loader) 的文档中收集到的内容是,如果 ArrayList 包含非原始 class ,我们必须使用 ClassLoader .

在这个使用 ClassLoader 的场景中有什么用例以及如何使用它?我想在接下来的事情中使用 ClassLoader。添加了一个成员变量private ArrayList<RandomClass> listRandom; RandomClass randomClass;来实现这个。

我的 FilterData class 持有:

public FilterData(Parcel parcel)
{
    listPropertyType=parcel.readArrayList(null);
    listRandom=parcel.readArrayList(randomClass);
}



 @Override
public void writeToParcel(Parcel parcel, int i) {
    parcel.writeList(listPropertyType);
    parcel.writeList(listRandom);
}

我的随机Class是:

public class RandomClass extends ClassLoader{

//this class is for testing classloader in ArrayList in parcelable .readArrayList()

String name;
int age;

public RandomClass(String name, int age) {
    this.name = name;
    this.age = age;
}
}

此实现无效。那么这个怎么用呢?

如果您从包裹中读取的数组列表是您创建的子类,而不是标准的 java 列表子类,或者如果它包含非基本类型,则需要传递 MyCustomList.class.getClassLoader().

你需要这样做,因为parcelables可以随时随地膨胀,所以代码必须知道加载它所需的ClassLoader。大多数时候你不需要它,因为你会在你自己的应用程序中打包东西,但这是一个很好的做法。

其实你说的是一个简单的列表ArrayList<String>,所以你什么都不用做。如果它是 MyListSubclass<String>ArrayList<MyObject> 或可能包含其他子类对象的 ArrayList<HashMap<Object, Object>>,则情况会有所不同。你明白了。

首先,如果我们想得到一个classParcelable,我们可以使用一个网站www.parcelabler.com。它将生成 class 的语法。其次,如果我们想使用我们自己的 class 的 ArrayList。制作一个包含 ArrayList 的 Parcelable class 是行不通的。我们还需要自定义 class Parcelable

如果一个需要parcelable的class包含一个成员变量ArrayList<String> list;,则网站生成的class应该是:

public class MyParcelable implements Parcelable {
ArrayList<String>  list;

public MyParcelable(ArrayList<String> list) {
    this.list = list;
}

protected MyParcelable(Parcel in) {
    if (in.readByte() == 0x01) {
        list = new ArrayList<String>();
        in.readList(list, String.class.getClassLoader());
    } else {
        list = null;
    }
}

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    if (list == null) {
        dest.writeByte((byte) (0x00));
    } else {
        dest.writeByte((byte) (0x01));
        dest.writeList(list);
    }
}

@SuppressWarnings("unused")
public static final Parcelable.Creator<MyParcelable> CREATOR = new Parcelable.Creator<MyParcelable>() {
    @Override
    public MyParcelable createFromParcel(Parcel in) {
        return new MyParcelable(in);
    }

    @Override
    public MyParcelable[] newArray(int size) {
        return new MyParcelable[size];
    }
};

}

如果 Class 包含我们这样制作的 class 的 ArrayList ArrayList<DummyClass> list; ,代码应该是:

public class MyComplexParcelable implements Parcelable {

ArrayList<DummyClass> list;

public MyComplexParcelable(ArrayList<DummyClass> list) {
    this.list = list;
}

@Override
public String toString() {
    return "MyComplexParcelable{" +
            "list=" + list +
            '}';
}

protected MyComplexParcelable(Parcel in) {
    if (in.readByte() == 0x01) {
        list = new ArrayList<DummyClass>();
        in.readList(list, DummyClass.class.getClassLoader());
    } else {
        list = null;
    }
}

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    if (list == null) {
        dest.writeByte((byte) (0x00));
    } else {
        dest.writeByte((byte) (0x01));
        dest.writeList(list);
    }
}

@SuppressWarnings("unused")
public static final Parcelable.Creator<MyComplexParcelable> CREATOR = new Parcelable.Creator<MyComplexParcelable>() {
    @Override
    public MyComplexParcelable createFromParcel(Parcel in) {
        return new MyComplexParcelable(in);
    }

    @Override
    public MyComplexParcelable[] newArray(int size) {
        return new MyComplexParcelable[size];
    }
};

}

如果我们比较这两种情况,语法上没有区别。 class 都使用 in.readList(list, String.class.getClassLoader());in.readList(list, DummyClass.class.getClassLoader()); 都使用对应 classes.

的 ClassLoader 对象

但在后一种情况下,我们需要使 DummyClass 可打包。像这样:

public class DummyClass implements Parcelable {
int age;
String name;

public DummyClass(int age, String name) {
    this.age = age;
    this.name = name;
}

@Override
public String toString() {
    return "DummyClass{" +
            "age=" + age +
            ", name='" + name + '\'' +
            '}';
}

protected DummyClass(Parcel in) {
    age = in.readInt();
    name = in.readString();
}

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeInt(age);
    dest.writeString(name);
}

@SuppressWarnings("unused")
public static final Parcelable.Creator<DummyClass> CREATOR = new Parcelable.Creator<DummyClass>() {
    @Override
    public DummyClass createFromParcel(Parcel in) {
        return new DummyClass(in);
    }

    @Override
    public DummyClass[] newArray(int size) {
        return new DummyClass[size];
    }
};
}