android开发之Serializable与Parcelable的使用

本文详细探讨了序列化在 Java 和 Android 中的作用,包括数据持久化、网络传输和进程间通信。对比了 Serializable 和 Parcelable 的性能,强调了在 Android 开发中,除非需要数据持久化,否则推荐使用 Parcelable 进行对象序列化,因其在内存管理和效率上表现更优。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为什么要序列化

(1).永久的保存对象数据(将对象数据保存在文件当中,或者是磁盘中
(2).通过序列化操作将对象数据在网络上进行传输(由于网络传输是以字节流的方式对数据进行传输的.因此序列化的目的是将对象数据转换成字节流的形式)
(3).将对象数据在进程之间进行传递(Activity之间传递对象数据时,需要在当前的Activity中对对象数据进行序列化操作.在另一个Activity中需要进行反序列化操作讲数据取出)
(4).Java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比JVM的生命周期更长(即每个对象都在JVM中)但在现实应用中,就可能要停止JVM运行,但有要保存某些指定的对象,并在将来重新读取被保存的对象。这是Java对象序列化就能够实现该功能。(可选择入数据库、或文件的形式保存)
(5).序列化对象的时候只是针对变量进行序列化,不针对方法进行序列化.
(6).在Intent之间,基本的数据类型直接进行相关传递即可,但是一旦数据类型比较复杂的时候,就需要进行序列化操作了.

实现序列化的二种方式:

Implements Serializable 接口 (声明一下即可)
Implements Parcelable 接口(不仅仅需要声明,还需要实现内部的相应方法)

Parcelable与Serializable的性能比较

Parcelable的性能要强于Serializable的原因
1). 在内存的使用中,前者在性能方面要强于后者
2). 后者在序列化操作的时候会产生大量的临时变量,(原因是使用了反射机制)从而导致GC的频繁调用,因此在性能上会稍微逊色
3). Parcelable是以Ibinder作为信息载体的.在内存上的开销比较小,因此在内存之间进行数据传递的时候,Android推荐使用Parcelable,既然是内存方面比价有优势,那么自然就要优先选择.
4). 在读写数据的时候,Parcelable是在内存中直接进行读写,而Serializable是通过使用IO流的形式将数据读写入在硬盘上.

但是:虽然Parcelable的性能要强于Serializable,但是仍然有特殊的情况需要使用Serializable,而不去使用Parcelable,因为Parcelable无法将数据进行持久化,因此在将数据保存在磁盘的时候,仍然需要使用后者,因为前者无法很好的将数据进行持久化.(原因是在不同的Android版本当中,Parcelable可能会不同,因此数据的持久化方面仍然是使用Serializable)

Demo

Address 类:通过实现Serializable 接口:

import java.io.Serializable;

public class Address implements Serializable {

    private static final long serialVersionUID = 81L;

    private String location;

    public Address(String location) {
        this.location = location;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    @Override
    public String toString() {
        return "Address{" +
                "location='" + location + '\'' +
                '}';
    }
}

类Person_Serializable :通过实现接口Serializable来实现序列化

package com.mediatek.serializable_parcelable_demo;

import java.io.Serializable;

public class Person_Serializable implements Serializable {

    private static final long serialVersionUID = -7060210544600464481L;

    private static int code_static = 0;//static value can not serializable
    private transient int code_transient = 1;//transient value can not serializable

    private String name;
    private int age;
    private Address address;

    public Person_Serializable(String name, int age,Address address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

类Person_Parcelable ,通过实现Parcelable 来实现序列化.

package com.mediatek.serializable_parcelable_demo;

import android.os.Parcel;
import android.os.Parcelable;

public class Person_Parcelable implements Parcelable {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

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

    public static final Parcelable.Creator<Person_Parcelable> CREATOR = new Creator<Person_Parcelable>(){

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

        @Override
        public Person_Parcelable createFromParcel(Parcel in){
            return new Person_Parcelable(in);
        }
    };

    public Person_Parcelable(Parcel in) {
        //如果元素数据是list类型的时候需要: lits = new ArrayList<?> in.readList(list);
        //否则会出现空指针异常.并且读出和写入的数据类型必须相同.如果不想对部分关键字进行序列化,
        // 可以使用transient关键字来修饰以及static修饰.
        name = in.readString();
        age = in.readInt();
    }

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

Help 类:实现对象的序列化和反序列化

package com.mediatek.serializable_parcelable_demo;

import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Help {

    private static final String TAG = "Help";

    public static void writeSerializable(String path,Person_Serializable person){
        File file = new File(path);
        if(file.exists()){
            file.delete();
        }

        FileOutputStream fos = null;
        ObjectOutputStream oos = null;

        try {
            fos = new FileOutputStream(file);
            oos = new ObjectOutputStream(fos);
            Log.i(TAG,"writeSerializable--persron:" + person);
            oos.writeObject(person);
            oos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(oos != null){
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fos != null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static Person_Serializable readSerializable(String path){
        Person_Serializable person = null;
        File file = new File(path);
        if(!file.exists()){
            return null;
        }

        FileInputStream fis = null;
        ObjectInputStream ois = null;

        try {
            fis = new FileInputStream(file);
            ois = new ObjectInputStream(fis);
            person = (Person_Serializable)ois.readObject();
            Log.i(TAG,"readSerializable--person:" + person);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        }catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally {
            if(ois != null){
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return person;
        }

    }
}

MainActivity 类:

package com.mediatek.serializable_parcelable_demo;

import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    private static Address address = new Address("shengzheng");
    public static Person_Serializable person =
            new Person_Serializable("xili",2,address);

    private Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }

    private void init() {
        button = (Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Person_Parcelable person_Parcelable = new Person_Parcelable("parcelable",20);
                Bundle bundle = new Bundle();
                bundle.putParcelable("parcelable", person_Parcelable);
                Intent intent = new Intent(MainActivity.this,SecondActivity.class);
                intent.putExtras(bundle);
                startActivity(intent);
            }
        });

        String path = "/sdcard/serializable.xml";
        Help.writeSerializable(path,person);
        Help.readSerializable(path);

    }
}

SecondActivity 类,实现对象使用Parcelable的方式在二个activity之间传递对象.

package com.mediatek.serializable_parcelable_demo;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

public class SecondActivity extends AppCompatActivity {

    private static String TAG = "SecondActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        init();
    }

    private void init() {
        Intent intent = getIntent();
        Bundle bun = intent.getExtras();
        Person_Parcelable person_Parcelable = bun.getParcelable("parcelable");
        Log.i(TAG,"person_Parcelable:" + person_Parcelable);
    }
}

需要在AndroidManifest.xml中定义sd卡的读写权限:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

日志输出

I Help    : writeSerializable--persron:Person_Serializable{name='xili', age=2, address=Address{location='shengzheng'}}
I Help    : readSerializable--person:Person_Serializable{name='xili', age=2, address=Address{location='shengzheng'}}

I SecondActivity: person_Parcelable:Person_Parcelable{name='parcelable', age=20}

总结:

Java应用程序中有Serializable来实现序列化操作,Android中有Parcelable来实现序列化操作,相关的性能也作出了比较,因此在Android中除了对数据持久化的时候需要使用到Serializable来实现序列化操作,其他的时候我们仍然需要使用Parcelable来实现序列化操作,因为在Android中效率并不是最重要的,而是内存,通过比较Parcelable在效率和内存上都要优秀与Serializable,尽管Parcelable实现起来比较复杂,但是如果我们想要成为一名优秀的Android软件工程师,那么我们就需要勤快一些去实现Parcelable,而不是偷懒与实现Serializable.

参考资料

1.https://blog.youkuaiyun.com/u012233285/article/details/77895822
java中Serializable与Parcelable的使用

2.https://www.cnblogs.com/yezhennan/p/5527506.html
Android中Serializable和Parcelable序列化对象详解

### BIND 安装失败的原因与解决方案 BIND (Berkeley Internet Name Domain) 是互联网上广泛使用的域名系统(DNS)服务器软件。当遇到BIND安装失败的情况时,通常可以从以下几个方面排查问题: #### 1. 权限不足 如果在执行 `named-checkconf` 或者启动 BIND 服务时收到权限错误的信息,则可能是由于当前用户缺乏足够的权限来读取配置文件或写入日志文件。建议使用超级用户权限尝试重新运行命令[^2]。 #### 2. 配置文件语法错误 BIND 对其配置文件 `/etc/named.conf` 及区域数据文件有严格的格式要求。任何细微的拼写失误都可能导致解析失败。可以利用工具如 `named-checkconf` 和 `named-checkzone` 来验证配置的有效性[^1]。 ```bash $ named-checkconf /etc/named.conf $ named-checkzone example.com /var/named/example.db ``` #### 3. 文件路径不正确 指定给 BIND 的某些重要文件(比如根提示文件、密钥文件等)可能不存在于预期位置,或是相对路径被误解成绝对路径。确认所有提到的具体文件确实存在于所指明的位置,并且 BIND 进程能够访问这些资源。 #### 4. 端口冲突 DNS 协议默认监听 UDP/TCP 上的端口号 53 。如果有其他程序占用了这个端口,那么即使 BIND 成功加载也会因为无法绑定到所需端口而崩溃退出。通过 netstat 命令检查是否有进程正在占用端口。 ```bash $ sudo netstat -tulnp | grep :53 ``` #### 5. SELinux/AppArmor 设置不当 安全增强型 Linux(Security-Enhanced Linux, SELinux) 或 AppArmor 类似的安全模块可能会阻止 BIND 正常工作。对于启用了此类功能的操作系统来说,应该适当调整策略规则以允许必要的网络通信和服务操作。 #### 6. 资源限制过高 有时操作系统级别的设置会施加过严苛的资源配额控制,例如最大打开文件数(`nofile`)、内存锁定大小(`memlock`)等,这会影响 BIND 启动过程中的性能表现甚至导致失败。查看并修改相应的 sysctl 参数可以帮助解决问题。 ```bash # 修改临时生效的方法 $ ulimit -n 65535 # 提高可打开的最大文件数量 $ sysctl -w fs.file-max=2097152 # 设定全局最大的文件句柄数目 # 若要永久更改,请编辑/etc/security/limits.conf以及/etc/sysctl.conf文件 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hfreeman2008

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值