Messenger 传递 List对象
假设需要传递的List对象为:
List<MyData> list = new ArrayList<>();
类 MyData 的定义为:
public class MyData implements Parcelable {
public int id;
public String name;
public MyData(int _id, String _name) {
this.id = _id;
this.name = _name;
}
public static final Creator<MyData> CREATOR = new Creator<MyData>() {
@Override
public MyData createFromParcel(Parcel in)
{
return new MyData(in);
}
@Override
public MyData[] newArray(int size)
{
return new MyData[size];
}
};
@Override
public int describeContents()
{
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags)
{
dest.writeInt(id);
dest.writeString(name);
}
}
在服务端的Messenger中将List对象放到bundle中传递List对象
List<MyData> list = getMyDataList();
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("list", list);
msgToClient.setData(bundle);
try {
msgfromClient.replyTo.send(msgToClient);
} catch (RemoteException e){
e.printStackTrace();
}
一切看起来没任何问题,所有步骤都是对的, MyData对象也序列化了。
但是这行会报错bundle.putParcelableArrayList("list", list);
说是list对象未序列化,查了下确实是,于是改为ArrayList。修改后如下:
ArrayList arrayList = new ArrayList<>();
List<MyData> list = getMyDataList();
arrayList.add(list);
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("list", arrayList);
msgToClient.setData(bundle);
try {
msgfromClient.replyTo.send(msgToClient);
} catch (RemoteException e){
e.printStackTrace();
}
修改后不报错了,然后写客户端代码。
在客户端接收该对象
Bundle data = msgFromServer.getData();
ArrayList list = data.getParcelableArrayList("list")
List<MyData> mList = (List<MyData>) list.get(0);
结果运行的时候直接crash,报错:
ClassNotFoundException when unmarshalling.....找不到com.xxx.xxx.MyData
报错的是这行:ArrayList list = data.getParcelableArrayList("list")
一脸懵逼。。。
百度了一翻后,在stackoverflow看到了一个感觉可行的方法:
Bundle data = msgFromServer.getData();
data.setClassLoader(MyData.class.getClassLoader());//加上这行
ArrayList list = data.getParcelableArrayList("list")
List<MyData> mList = (List<MyData>) list.get(0);
还真是可以了...
总结:
1. Bundle传递对象一定要序列化,Android推荐用Parcelable,不解释。
2. ArrayList可以直接传递,因为已经序列化,看源码就知道。
ArrayList: public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
而List没有:
List: public interface List<E> extends Collection<E>
3. 在Android上classloader是个蛋疼的东西,深究下去估计是个bug。查看Parcel.java源码,找到when unmarshalling关键字,调用的是readParcelableCreator这个函数,
参数就是ClassLoader,而报ClassNotFoundException就是掉用Class<?> parcelableClass = Class.forName(name, false /* initialize */,parcelableClassLoader);导致的。
这里的name应该是拿到了ArrayList,而不是MyData.所以需要指定。
/** @hide */
public final Parcelable.Creator<?> readParcelableCreator(ClassLoader loader) {
String name = readString();
if (name == null) {
return null;
}
Parcelable.Creator<?> creator;
synchronized (mCreators) {
HashMap<String,Parcelable.Creator<?>> map = mCreators.get(loader);
if (map == null) {
map = new HashMap<>();
mCreators.put(loader, map);
}
creator = map.get(name);
if (creator == null) {
try {
// If loader == null, explicitly emulate Class.forName(String) "caller
// classloader" behavior.
ClassLoader parcelableClassLoader =
(loader == null ? getClass().getClassLoader() : loader);
// Avoid initializing the Parcelable class until we know it implements
// Parcelable and has the necessary CREATOR field. http://b/1171613.
Class<?> parcelableClass = Class.forName(name, false /* initialize */,
parcelableClassLoader);
if (!Parcelable.class.isAssignableFrom(parcelableClass)) {
throw new BadParcelableException("Parcelable protocol requires that the "
+ "class implements Parcelable");
}
Field f = parcelableClass.getField("CREATOR");
if ((f.getModifiers() & Modifier.STATIC) == 0) {
throw new BadParcelableException("Parcelable protocol requires "
+ "the CREATOR object to be static on class " + name);
}
Class<?> creatorType = f.getType();
if (!Parcelable.Creator.class.isAssignableFrom(creatorType)) {
// Fail before calling Field.get(), not after, to avoid initializing
// parcelableClass unnecessarily.
throw new BadParcelableException("Parcelable protocol requires a "
+ "Parcelable.Creator object called "
+ "CREATOR on class " + name);
}
creator = (Parcelable.Creator<?>) f.get(null);
}
catch (IllegalAccessException e) {
Log.e(TAG, "Illegal access when unmarshalling: " + name, e);
throw new BadParcelableException(
"IllegalAccessException when unmarshalling: " + name);
}
catch (ClassNotFoundException e) {
Log.e(TAG, "Class not found when unmarshalling: " + name, e);
throw new BadParcelableException(
"ClassNotFoundException when unmarshalling: " + name);
}
catch (NoSuchFieldException e) {
throw new BadParcelableException("Parcelable protocol requires a "
+ "Parcelable.Creator object called "
+ "CREATOR on class " + name);
}
if (creator == null) {
throw new BadParcelableException("Parcelable protocol requires a "
+ "non-null Parcelable.Creator object called "
+ "CREATOR on class " + name);
}
map.put(name, creator);
}
}
return creator;
}
Messenger 传递 List对象以及遇到的问题
猜你喜欢
转载自blog.csdn.net/LikeSidehu/article/details/121610444
今日推荐
周排行