ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

面试系列(二)Android中的序列化

2021-08-01 16:34:02  阅读:296  来源: 互联网

标签:Parcelable Serializable 面试 cList Android 序列化 public serialVersionUID


文章目录

序列化

为什么要序列化

在进行 Android 开发的时候,无法将对象的引用传递给 Activity 或者 Fragment,我们需要将这些对象放到一个 Intent 或者 Bundle 里面,然后进行传递。但是 Intent 或者是 Bundle 中只能存放进行过序列化后的对象。

什么是序列化

序列化,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。

反序列化

反序列化就是序列化的逆过程,将网络上传输的字节流、本地存储的文件中的内容读取转换为一个对象的过程。

怎么实现序列化

Android 中 Intent 如果要传递类对象,可以通过两种方式。

  • 方式一:Serializable,要传递的类实现 Serializable 接口
  • 方式二:Parcelable,要传递的类实现 Parcelable 接口

Serializable(Java 自带的)

Serializable 是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。 Serializable 接口是一种标识接口,也就是无需实现方法,Java 便会对这个对象进行序列化操作。

serialVersionUID 的作用

  • 类的 serialVersionUID 的默认值完全依赖于 Java 编译器的实现,对于同一个类,用不同的 Java 编译器编译,也有可能会导致不同的serialVersionUID。所以 IDE 才会提示声明 serialVersionUID 的值。
  • 不定义 serialVersionUID 时,Java 会根据类的细节自动生成 serialVersionUID 的值,如果对类的源码做了修改,再重新编译,生成的类的 serialVersionUID 的取值可能会变化,再次反序列化时,若 serialVersionUID 不相等会 crash。
  • 不修改 serialVersionUID,但是 bean 的属性发生改变,则反序列化时此属性会为空,读不到值(取兼容老版本的作用)
  • 只要反序列化时 serialVersionUID 不相等,就会 InvalidClassException Crash

Parcelable(Android 专用)

除了 Serializable 之外,使用 Parcelable 也可以实现相同的效果,
不过不同于将对象进行序列化,Parcelable 方式的实现原理是将一个完整的对象进行分解, 而分解后的每一部分都是 Intent 所支持的数据类型,这样也就实现传递对象的功能了。

两者的区别

两者最大的区别在于存储媒介的不同Serializable 使用 I/O 读写存储在硬盘上。而 Parcelable 是直接 在内存中读写。很明显,内存的读写速度通常大于 IO 读写,所以在 Android 中传递数据优先选择 Parcelable。

Serializable 会使用反射,序列化和反序列化过程需要大量 I/O 操作,序列化过程中会创建很多临时对象,容易触发垃圾回收;Parcelable 自已实现封送和解封(marshalled &unmarshalled)操作,不需要用反射,数据也存放在内存中,效率要快很多。

继承一个实现了 Parcelable 接口的类需要注意的地方

B 类实现了 Parcelable 接口,A 继承自 B,则 A 不需要再实现 Parcelable 接口,但是 A 需要实现相应的抽象方法:describeContents、writeToParcel 还有 CREATOR 构造器等等。还要在 writeToParcel 和相应的构造函数中调用 super 方法。如下,CourseEvent 实现了 Parcelable 接口。

CourseEvent 类:

public class CourseEvent extends ResponseEvent implements Parcelable {
    protected List<CourseInfoDto> cList;      //课程列表
    protected long currentTime;               //socket发送时间戳

    public CourseEvent() {
    }

    protected CourseEvent(Parcel in) {
        cList = in.createTypedArrayList(CourseInfoDto.CREATOR);
        currentTime = in.readLong();
    }

    public static final Creator<CourseEvent> CREATOR = new Creator<CourseEvent>() {
        @Override
        public CourseEvent createFromParcel(Parcel in) {
        return new CourseEvent(in);
        }

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

    @Override
    public String toString() {
        return "CourseEvent{" +
            " cList=" + cList +
            ", currentTime=" + currentTime +
            '}';
    }

    public List<CourseInfoDto> getcList() {
        return cList;
    }

    public void setcList(List<CourseInfoDto> cList) {
        this.cList = cList;
    }

    public long getCurrentTime() {
        return currentTime;
    }

    public void setCurrentTime(long currentTime) {
        this.currentTime = currentTime;
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeTypedList(cList);
        dest.writeLong(currentTime);
    }
}

WgtCourseInfo 类:

public class WgtCourseInfo extends CourseEvent {

    private int cState;  //0:没上过任何课;1:上课中;2:下课啦

    public WgtCourseInfo() {
        super();
    }

    protected WgtCourseInfo(Parcel in) {
        super(in);
        cState = in.readInt();
    }

    public static final Creator<WgtCourseInfo> CREATOR = new Creator<WgtCourseInfo>() {
        @Override
        public WgtCourseInfo createFromParcel(Parcel in) {
            return new WgtCourseInfo(in);
        }

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

    @Override
    public String toString() {
        return "WgtCourseInfo{" +
            "cState=" + cState +
            ", cList=" + cList +
            ", currentTime=" + currentTime +
            '}';
    }

    public int getcState() {
        return cState;
    }

    public void setcState(int cState) {
        this.cState = cState;
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest, flags);
        dest.writeInt(cState);
    }
}

要记住一点,在 writeToParcel 中write 数据的顺序,要与在构造器中 read 的顺序相同

参考网站

序列化Serializable和Parcelable的理解和区别

Java serialVersionUID 的作用?

Parcelable接口的使用

Serializable 和 Parcelable 的区别

Extending a class that implements Parcelable

How to extend android class which implements Parcelable interface?

Is using Serializable in Android bad?

Android - Problem with the Serializable interface

Parcelable接口的使用

标签:Parcelable,Serializable,面试,cList,Android,序列化,public,serialVersionUID
来源: https://blog.csdn.net/SAberDepth/article/details/119299075

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有