Parcelable vs Serializable trong Android

Tam H. Doan
Viet Android Developers
4 min readJul 28, 2019

Originally published at http://www.iceteaviet.com on August 18th, 2016

Khi bắt đầu với lập trình Android, chúng ta đều được học rằng KHÔNG THỂ truyền trực tiếp tham chiếu của một đối tượng (object references) tới các Activity hoặc Fragment. Để đối mặt với vấn đề khó khăn này chúng ta phải “gói” chúng vào một Intent/Bundle.

Truyền những tham số có kiểu nguyên thủy (primitive data types) như là String, integer, float,.. qua Intent thì khá dễ dàng. Tất cả những gì bạn cần làm là put() dữ liệu với một key duy nhất làm từ khóa vào Intent và gửi nó đến một Activity bất kỳ, tuy nhiên với một custom object thì mọi thứ lại khác!

Nhìn vào API, ta nhận ra rằng có hai cách để truyền Java object qua Intent:

  • Implements từ Parcelable interface.
  • Implements từ Serializable interface.

Là một lập trình viên Java/C# chúng ta chắc hẳn đã biết rõ cơ chế hoạt động của Serializable, vậy tại sao ta lại phải bận tâm với Parcelable?

Serializable

Serializable đơn giản chỉ là một interface chung của Java.

Thế mạnh của Serializable là việc

đơn giản chỉ cần “đánh dấu” một class Serializable bằng cách implements interface đó lên nó và các class con của nó.

Sau đó máy ảo Java (Java Virtual Machine) sẽ tự động serialize class theo từng trường hợp khác nhau.

Đây là marker interface (một loại design pattern), bạn sẽ không cần phải cài đặt lại bất cứ method nào của nó khi implements.

Vấn đề với hướng tiếp cận này là Java Reflection được sử dụng, và nó làm tốc độ của app bị chậm đi. Cơ chế này thường tạo rất nhiều đối tượng tạm (temporary objects) và khi đó cơ chế dọn rác Garbage Collection của Java sẽ phải hoạt động liên tục dẫn đến tốn tài nguyên của thiết bị.

Parcelable

Parcelable là một interface riêng của Android. Nơi mà bạn phải tự cài đặt các hàm serialization một cách thủ công mà không được sự hỗ trợ từ JVM.

Parcelable cho phép chúng ta làm chủ quá trình convert một object (cùng các phần tử bên trong nó) thành một byte stream để truyền đi, sau đó convert byte stream đó ngược lại thành một object như ban đầu!

Hai hàm quan trọng của cơ chế này là:

  • void writeToParcel(Parcel dest, int flags)
  • Hàm dựngpublic MyObject(Parcel source)

Chúng dùng để qui định thứ tự serialize (marshalling/unmarshalling) của các phần tử trong một object.

Theo những gì mình đọc trên StackOverflow, hay theo các Google engineers thì Parcelable sẽ thực thi nhanh hơn. Một trong các lý do đó là chúng ta đã cài đặt tường minh các hàm thể hiện quá trình serialization thay vì sử dụng Java Reflection. Khi tối ưu hóa như vậy thì cơ chế dọn rác GC của Java sẽ làm việc ít hơn, làm app “chạy nhanh” hơn.

Tuy nhiên, rõ ràng cái gì cũng có cái giá của nó. Với hướng tiếp cận này chúng ta sẽ sinh ra “một đống” code khá dài dòng, và làm cho những class này rất khó đọc và fix bug, bảo trì sau này.

Kiểm tra tốc độ

Dĩ nhiên, chúng ta đều muốn biết Parcelable nhanh hơn tới mức nào!

Phương pháp:

  • Mô phỏng quá trình truyền object vào activity
  • Chạy quá trình đó trong vòng lặp 1000 lần
  • Chạy trung bình 10 lần khác nhau để tính dung lượng bộ nhớ, cpu chiếm dụng,..
  • Test trong nhiều thiết bị android (LG Nexus 4 — Android 4.2.2, Samsung Nexus 10 — Android 4.2.2, HTC Desire Z — Android 2.3.3)

Kết quả:

Thời gian thực thi của bộ test (hình ảnh và dữ liệu theo developerphil.com)

Tổng kết

Trong ví dụ trên, Android Parcelable tỏ ra nhanh hơn nhiều so với Java Serializable.

Một trong những lý do chính là do Parcelable được cài đặt bằng custom code, cho phép qui định thứ tự convert dữ liệu thành Parcel. Trong khi Serialazation convert đối tượng thành một data stream dựa vào Java Reflection API.

Nếu bạn muốn trở thành một lập trình viên giỏi, hãy bỏ thời gian để cài đặt Parcelable bởi vì nó có thể thực thi nhanh hơn từ 4–10 lần và sử dụng ít tài nguyên hơn, khiến GC hoạt động ít hơn.

Tuy nhiên trong nhiều trường hợp, sự “chậm chạp” của Serializable không đáng nhắc tới. Hãy thoải mái sử dụng nó đối với những class nhỏ, nhưng hãy nhớ là nó luôn “ngốn tài nguyên” nên hãy giảm thiểu đến mức đáng kể khi cần những đoạn code đẹp — dễ đọc và bảo trì. Còn nếu bạn đang muốn truyền một List với hàng nghìn objects, thì sự “chậm chạp” đó sẽ lên tới con số nhiều giây. Và khi đó chuyển động giao diện cũng như hiệu năng của ứng dụng sẽ trở nên khá tồi tệ và đó cũng là lúc cần dùng đến vị cứu tinh dành riêng cho lập trình viên Android — Parcelable.

Happy coding~

--

--