0

Parcelable và Serializable trong Android

Khi chúng ta bắt đầu làm quen với lập trình ứng dụng Android, chúng ta đã học được rằng không thể chỉ truyền object references giữa các activities hoặc fragments mà phải đặt nó vào trong Intent/Bundle.

Nhìn vào API chúng ta nhận ra rằng có 2 lựa chọn hoặc làm cho objects Parcelable hoặc Serializable. Nếu bạn đã từng lập trình Java thì chắc chắn bạn đã biết đến cơ chế Serializable, vậy tại sao trời đã sinh ra Serializable còn sinh ra Parcelable?

Để trả lời câu hỏi đó hãy nhìn vào 2 cách mà chúng làm việc.

I. Serializable, bậc thầy của sự đơn giản.

// access modifiers, accessors and constructors omitted for brevity
public class SerializableDeveloper implements Serializable
    String name;
    int yearsOfExperience;
    List<Skill> skillSet;
    float favoriteFloat;

    static class Skill implements Serializable {
        String name;
        boolean programmingRelated;
    }
}

Vẻ đẹp của serializable chính là bạn chỉ cần implement interface Serializable vào class và các sub class. Nó đơn giản là một interface marker không có bất cứ phương thức nào cần implement. Vấn đề với cách làm này đó chính là Java sẽ sử dụng reflaction để đọc ghi các dữ liệu nên sẽ bị chậm. Cơ chế này cũng tạo ra rất nhiều objects trung gian và dẫn đến nhiều tiến trình dọn rác.

II. Parcelable, Vua tốc độ

// access modifiers, accessors and regular constructors ommited for brevity
class ParcelableDeveloper implements Parcelable {
    String name;
    int yearsOfExperience;
    List<Skill> skillSet;
    float favoriteFloat;

    ParcelableDeveloper(Parcel in) {
        this.name = in.readString();
        this.yearsOfExperience = in.readInt();
        this.skillSet = new ArrayList<Skill>();
        in.readTypedList(skillSet, Skill.CREATOR);
        this.favoriteFloat = in.readFloat();
    }

    void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(yearsOfExperience);
        dest.writeTypedList(skillSet);
        dest.writeFloat(favoriteFloat);
    }

    int describeContents() {
        return 0;
    }


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

        ParcelableDeveloper createFromParcel(Parcel in) {
            return new ParcelableDeveloper(in);
        }

        ParcelableDeveloper[] newArray(int size) {
            return new ParcelableDeveloper[size];
        }
    };

    static class Skill implements Parcelable {
        String name;
        boolean programmingRelated;

        Skill(Parcel in) {
            this.name = in.readString();
            this.programmingRelated = (in.readInt() == 1);
        }

        @Override
        void writeToParcel(Parcel dest, int flags) {
            dest.writeString(name);
            dest.writeInt(programmingRelated ? 1 : 0);
        }

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

            Skill createFromParcel(Parcel in) {
                return new Skill(in);
            }

            Skill[] newArray(int size) {
                return new Skill[size];
            }
        };

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

Theo các kỹ sư của Google, đoạn code trên sẽ thực thi nhanh hơn đáng kể. Một trong những lý do cho việc đó chính là Parcelable thực hiện quá trình serialization một cách tường minh thay vì sử dụng reflaction. Tuy nhiên, không có cái gì vừa ngon vừa bổ lại còn rẻ cả. Khi implement Parcelable bạn cần thêm một lượng lớn code và làm cho class khó đọc khó maintain hơn.

III. SPEED TEST

Tất nhiên lý thuyết là vậy nhưng chúng ta mong muốn được biết trong thực tế Parcelable sẽ nhanh hơn Serializable bao nhiêu.

Cách thực hiện

  • Bắt chước quá trình truyền object vào activity bằng việc đặt object vào Bundle và gọi Bundle.wireToParcel(Parcel, int) sau đó lấy lại object đó.
  • Chạy trong vòng lặp 1000 lần
  • Tính trung bình 10 lần chạy và thống kê lượng memory được cấp phát, sử dụng cpu, vân vân
  • Các objects được test chính là SerializableDeveloper và ParcelableDeveloper bên trên
  • Test được thực hiện trên nhiều devices và android versions
    • LG Nexus 4 - Android 4.2.2
    • Samsung Nexus 10 - Android 4.2.2
    • HTC Desire Z - Android 2.3.3

Kết quả

Nexus 10 Serializable: 1.0004ms, Parcelable: 0.0850ms - 10.16x improvement.

Nexus 4 Serializable: 1.8539ms - Parcelable: 0.1824ms - 11.80x improvement.

Desire Z Serializable: 5.1224ms - Parcelable: 0.2938ms - 17.36x improvement.

Vậy là Parcelable nhanh hơn Serializable hơn 10 lần.

VI. KẾT LUẬN

Nếu bạn muốn làm một công dân tốt, hãy dành ra một khoảng thời gian để implement Parcelable bởi vì nó sẽ thực thi nhanh hơn 10 lần và sử dụng ít tài nguyên hơn. Tuy nhiên, trong đa số các trường hợp, sự chậm chạp của Serializable không đáng chú ý. Bạn có thể sử dụng nó nhưng hãy nhớ rằng quá trình serialization rất tốn chi phí nên hãy sử dụng nó ít nhất có thể. Nếu bạn có ý định truyền một list với hàng ngàn objects serialized, nó có thể chiếm đến hàng giây để thực hiện. Nó có thể là lí do cho việc roate từ landscape sang portrait có cảm giác chậm chạp.

HẾT (Nguồn)[http://www.developerphil.com/parcelable-vs-serializable/]


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí