android开发——跨进程通讯数据传递(三)
来源:互联网 发布:java求n的阶乘for循环 编辑:程序博客网 时间:2024/05/21 07:05
好了,承接上文,上问我们说道我们的新的需求——想要使得aidl能够传递可继承的类
aidl本身是不支持这样的,但是我们可以通过Parcelable进行构造的时候,去满足我们的需求
还记得在实现Parcelable时我们需要构造的其中一个静态类么?其中有这样的方法
public A createFromParcel(Parcel source) { return new A(source); }这里也就是决定了我们要实际构造的对象,换言之,我们可以在这个部分知道需要构造的对象类型问题就解决了~
于是,我们可以在构造函数改造成这样,并且修改createFromParcel,当接收到数据去构造对象时,第一件事就是读取类名
注意,Parcel调用一次read方法后,就会移除该部分数据
public A(Parcel in) { String className = in.readString(); try { //赋值给当前对象 rehydrate(this, in); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } public static final Parcelable.Creator<A> CREATOR = new Parcelable.Creator<A>() { public A createFromParcel(Parcel in) { Class<?> parceledClass; try { parceledClass = Class.forName(in.readString()); A model = (A) parceledClass.newInstance(); rehydrate(model, in); return model; } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return null; } public A[] newArray(int size) { return new A[size]; } }; @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(this.getClass().getName()); try { //将当前对象写入到dest中 dehydrate(this, dest); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } }
显然,现在的问题变成,我们通过rehydrate给对象赋值,通过dehydrate来将对象的数据写入
而这将依靠Class类中的newInstance()方法,之后通过反射,将对应数据进行复制
而为了能方便的写入对应字段的值,我们需要一个稳定的顺序,这里我们根据字段的类型来排序
完整的类A如下
public class A implements Parcelable { public A() { } public A(Parcel in) { String className = in.readString(); try { //赋值给当前对象 rehydrate(this, in); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } public static final Parcelable.Creator<A> CREATOR = new Parcelable.Creator<A>() { public A createFromParcel(Parcel in) { Class<?> parceledClass; try { parceledClass = Class.forName(in.readString()); A model = (A) parceledClass.newInstance(); rehydrate(model, in); return model; } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return null; } public A[] newArray(int size) { return new A[size]; } }; @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(this.getClass().getName()); try { //将当前对象写入到dest中 dehydrate(this, dest); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } //注意读取变量和写入变量的顺序应该一致 不然得不到正确的结果 public void readFromParcel(Parcel source) { Class<?> parceledClass; try { parceledClass = Class.forName(source.readString()); A model = (A) parceledClass.newInstance(); rehydrate(this, source); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } @Override public int describeContents() { return 0; } protected static void dehydrate(A model, Parcel out) throws IllegalArgumentException, IllegalAccessException { Field[] fields = model.getClass().getDeclaredFields(); Arrays.sort(fields, compareMemberByName); for (Field field : fields) { field.setAccessible(true); if (field.getType().equals(int.class)) { out.writeInt(field.getInt(model)); } else if (field.getType().equals(double.class)) { out.writeDouble(field.getDouble(model)); } else if (field.getType().equals(float.class)) { out.writeFloat(field.getFloat(model)); } else if (field.getType().equals(long.class)) { out.writeLong(field.getLong(model)); } else if (field.getType().equals(String.class)) { out.writeString((String) field.get(model)); } else if (field.getType().equals(boolean.class)) { out.writeByte(field.getBoolean(model) ? (byte) 1 : (byte) 0); } else if (A.class.isAssignableFrom(field.getType())) { Log.e("GlobalParcelable", "GlobalParcelable F*ck up: " + " (" + field.getType().toString() + ")"); out.writeParcelable((A) field.get(model), 0); } else { Log.e("GlobalParcelable", "Could not write field to parcel: " + " (" + field.getType().toString() + ")"); } } } protected static void rehydrate(A model, Parcel in) throws IllegalArgumentException, IllegalAccessException { Field[] fields = model.getClass().getDeclaredFields(); Arrays.sort(fields, compareMemberByName); // populate the fields for (Field field : fields) { field.setAccessible(true); if (field.getType().equals(int.class)) { field.set(model, in.readInt()); } else if (field.getType().equals(double.class)) { field.set(model, in.readDouble()); } else if (field.getType().equals(float.class)) { field.set(model, in.readFloat()); } else if (field.getType().equals(long.class)) { field.set(model, in.readLong()); } else if (field.getType().equals(String.class)) { field.set(model, in.readString()); } else if (field.getType().equals(boolean.class)) { field.set(model, in.readByte() == 1); } else if (A.class.isAssignableFrom(field.getType())) { Log.e("GlobalParcelable", "read GlobalParcelable: " + " (" + field.getType().toString() + ")"); field.set(model, in.readParcelable(field.getType().getClassLoader())); } else { Log.e("GlobalParcelable", "Could not read field from parcel: " + field.getName() + " (" + field.getType().toString() + ")"); } } } /* * Comparator object for Members, Fields, and Methods */ private static Comparator<Field> compareMemberByName = new CompareMemberByName(); private static class CompareMemberByName implements Comparator { public int compare(Object o1, Object o2) { String s1 = ((Member) o1).getName(); String s2 = ((Member) o2).getName(); if (o1 instanceof Method) { s1 += getSignature((Method) o1); s2 += getSignature((Method) o2); } else if (o1 instanceof Constructor) { s1 += getSignature((Constructor) o1); s2 += getSignature((Constructor) o2); } return s1.compareTo(s2); } } private static String getSignature(Class clazz) { String type = null; if (clazz.isArray()) { Class cl = clazz; int dimensions = 0; while (cl.isArray()) { dimensions++; cl = cl.getComponentType(); } StringBuffer sb = new StringBuffer(); for (int i = 0; i < dimensions; i++) { sb.append("["); } sb.append(getSignature(cl)); type = sb.toString(); } else if (clazz.isPrimitive()) { if (clazz == Integer.TYPE) { type = "I"; } else if (clazz == Byte.TYPE) { type = "B"; } else if (clazz == Long.TYPE) { type = "J"; } else if (clazz == Float.TYPE) { type = "F"; } else if (clazz == Double.TYPE) { type = "D"; } else if (clazz == Short.TYPE) { type = "S"; } else if (clazz == Character.TYPE) { type = "C"; } else if (clazz == Boolean.TYPE) { type = "Z"; } else if (clazz == Void.TYPE) { type = "V"; } } else { type = "L" + clazz.getName().replace('.', '/') + ";"; } return type; } private static String getSignature(Method meth) { StringBuffer sb = new StringBuffer(); sb.append("("); Class[] params = meth.getParameterTypes(); // avoid clone for (int j = 0; j < params.length; j++) { sb.append(getSignature(params[j])); } sb.append(")"); sb.append(getSignature(meth.getReturnType())); return sb.toString(); } private static String getSignature(Constructor cons) { StringBuffer sb = new StringBuffer(); sb.append("("); Class[] params = cons.getParameterTypes(); // avoid clone for (int j = 0; j < params.length; j++) { sb.append(getSignature(params[j])); } sb.append(")V"); return sb.toString(); }}
至此,一个支持aidl继承功能的基类A就ok了~
接下来我们可以派生一个子类B,并通过aidl传递过去,再在binder线程中强制转化为类B进行输出
这方面的代码就不贴出了,有心的读者可以自己尝试下
0 0
- android开发——跨进程通讯数据传递(三)
- android开发——跨进程通讯数据传递(一)
- android开发——跨进程通讯数据传递(二)
- Android跨进程通讯
- cameraservice如何跨进程传递video数据——类图
- android中跨进程通讯
- Android AIDL跨进程通讯
- android 跨进程通讯详解
- android AIDL,跨进程通讯
- Android开发中实现跨进程通讯的AIDL接口
- Android开发中实现跨进程通讯的AIDL接口
- Android开发中实现跨进程通讯的AIDL接口
- 进程间通讯—MFC三种消息传递数据
- android中跨进程数据传递和访问
- Android AIDL Service 跨进程传递复杂数据
- Android AIDL Service 跨进程传递复杂数据
- Android AIDL Service 跨进程传递复杂数据
- Android AIDL Service 跨进程传递复杂数据
- openlayers基础知识
- 怎么用HTML写微信弹幕效果
- http与https的区别
- 怎么去除MIUI7中日历的广告(超简单)
- iso 上架
- android开发——跨进程通讯数据传递(三)
- RemoteViews在通知栏和小组件中的应用
- Java 8 中 HashMap 的性能提升
- 实战:基于ESB的企业系统集成
- 在Dialog中button与回车键
- html页面自动滚动
- hdoj-1026--Ignatius and the Princess I---BFS+优先队列(每次先用用时最少的点进行扩展)【A*】
- 网络IO,阻塞,非阻塞,异步,同步io的总结
- BZoj 2463: [中山市选2009]谁能赢呢?【博弈】