android開發之Serializable與Parcelable的使用

爲什麼要序列化

(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.csdn.net/u012233285/article/details/77895822
java中Serializable與Parcelable的使用

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章