• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

Android-使用序列化Serializable和Parcelable

android 搞代码 3年前 (2022-03-01) 23次浏览 已收录 0个评论

Android 序列化Serializable和Parcelable应用和区别

一:Serializable

1.什么是序列化
将一个类对象转换成可存储,可传输状态的过程。
2.什么是Serializable接口
一个对象序列化的接口,一个类只有实现了Serializable接口,它的对象能力被序列化。
3.为什么要序列化对象
1.把对象转换为字节序列的过程称为对象的序列化
2.把字节序列复原为对象的过程称为对象的反序列化
4.序列化用处
1.想把对象的状态信息通过网络进行传输
2.须要把对象长久化存储,存储在文件,数据库等

public class User implements Serializable {
 private static final long serialVersionUID = 1L;
 private String name;
 private int age;
 public String getName() {
        return name;
 }
    public void setName(String name) {
        this.name = name;
 }
    public int getAge() {
        return age;
 }
    public void setAge(int age) {
        this.age = age;
 }
}

当我跟进去,发现Serializable是一个空接口,一个接口什么都没有,咱们能够将它了解成一个标识接口

例如:在课堂上有位学生遇到一个问题,于是举手向老师求教,这时老师帮他解答,那么这位学生的举手其实就是一个标识,本人解决不了问题求教老师帮忙解决。在Java中的这个Serializable接口其实是给jvm看的,告诉jvm,我不对这个类做序列化了,你(jvm)帮我序列化就好了。


5.为什么要定义serialVersionUID变量

从阐明中能够看出,如果咱们没有本人申明一个serialVersionUID变量,接口会默认生成一个serialVersionUID
*然而强烈建议用户自定义一个serialVersionUID,因为默认的serialVersionUID对于class的细节十分敏感,反序列化时可能会导致
InvalidClassException这个异样。*
5.transient关键字
用来示意一个成员变量不是该对象序列化的一部分。当一个对象被序列化的时候,transient型变量的值不包含在序列化后果中。注:static润饰的动态变量人造的就是不可序列化的

private static final long serialVersionUID = 1L;
private String name;
private transient int age;

transient关键字只能润饰变量,而不能润饰办法和类。
被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。

二:Parcelable

Parcelable是Android为咱们提供的序列化的接口,Parcelable的效率绝对于Serializable也高许多。
Parcelable不能应用在要将数据存储在磁盘上状况
在内存中应用Parcelable性能优于Serializable

public class User implements Parcelable {
 private String name;
 private int age;
 public User(String name, int age) {
 this.name = name;
 this.age = age;
}
 /**
 * 从序列化后的对象中创立原始数据*/
 protected User(Parcel in) {
        name = in.readString();
 age = in.readInt();
 }
    /**
 * 序列化:将以后对象写入序列化构造中
 */
 @Override
 public void writeToParcel(Parcel dest, int flags) {
 dest.writeString(name);
 dest.writeInt(age);
 }
    /**
 * 以后对象的内容形容,存在文件描述符时返回1,其余全返回0
 */
 @Override
 public int describeContents() {
        return 0;
 }
    /**
 * 反序列化
 */
 public static final Creator<User> CREATOR = new Creator<User>() {
        /**
 * 将序列化对象中创立原始数据*/
 @Override
 public User createFromParcel(Parcel in) {
            return new User(in);
 }
        /**
 * 创立指定长度的原始对象数组*/
 @Override
 public User[] newArray(int size) {
            return new User[size];
 }
    };
 @Override
 public String toString() {
        return "User{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
 }
}

1.Parcel英文译为包裹,Android采纳这个词示意封装音讯的数据。这个通过IBinder通信的音讯载体。Parcel用来存放数据的内存(RAM),而不是永恒介质。

//获取一个Parcel容器
Parcel parcel=Parcel.obtain();
//须要序列化的对象
User user=new User("mike",13);
//把对象写入Parcel
parcel.writeParcelable(user,0);
//Parcel读写共用一个地位计数,这里肯定要重置一下以后的地位
parcel.setDataPosition(0);
//读取Parcel
User user1=parcel.readParcelable(User.class.getClassLoader());
Log.d("LoginActivity",user1.toString());

调用parcel.writeParcelable(user,0);源码解析

public final void writeParcelable(@Nullable Parcelable p, int parcelableFlags) {
//判断p是否为空
    if (p == null) {
        writeString(null);
 return; }
 //先写入P的类名(user就是p类类名)
    writeParcelableCreator(p);
  //调用咱们重写的writeToParcel办法,按程序写入
 p.writeToParcel(this, parcelableFlags);
}
/** @hide */
@UnsupportedAppUsage
public final void writeParcelableCreator(@NonNull Parcelable p) {
//写入p类的类名
    String name = p.getClass().getName();
 writeString(name);
}

调用parcel.readParcelable(User.class.getClassLoader());源码解析

public final <T extends Parcelable> T readParcelable(@Nullable ClassLoader loader) {
//调用readParcelableCreator
//这时咱们获取就是咱们自定义的CREATOR
    Parcelable.Creator<?> creator = readParcelableCreator(loader);
 if (creator == null) {
        return null;
 }
 // 判断以后creator是不是Parcelable.ClassLoaderCreator<?>的实例
    if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
    //如果是的话,,咱们调用reateFromParcel(this, loader)
      Parcelable.ClassLoaderCreator<?> classLoaderCreator =
          (Parcelable.ClassLoaderCreator<?>) creator;
 return (T) classLoaderCreator.createFromParcel(this, loader);
 }
   //调用咱们自定义的CREATOR中重写的createFromParcel办法
    return (T) creator.createFromParcel(this);
}
public final Parcelable.Creator<?> readParcelableCreator(@Nullable ClassLoader loader) {
//首先把类名读取进去
    String name = readString();
 if (name == null) {
        return null;
 }
    Parcelable.Creator<?> creator;
     //mCreators做了一下缓存,如果之前某个classloader把一个parcelable的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 subclassing "
 + "from Parcelable on class " + name);
 }
                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;
}

搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Android-使用序列化Serializable和Parcelable

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址