Chào các bạn!
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 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 Intents thì khá dễ dàng trong Android. 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ỳ.
Nhìn vào API, ta nhận ra rằng có hai cách để truyền Java object qua Intent: một là implements Java class đó từ Percelable interface, hai là 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?
Để trả lời câu hỏi đó, hay tiếp cận rõ hơn để xem tại sao như vậy nhé!
SERIALIZABLE - BẬC THẦY CỦA SỰ ĐƠN GIẢN
Serializable là một interface chuẩn của Java. Vẻ đẹp của Serializable là việc bạn đơ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à một marker interface, nghĩa là không cần phải cài đặt lại bất cứ method nào của khi implements.
Vấn đề xảy ra với hướng tiếp cận này là Java Reflection được sử dụng, và nó làm tiến trình của phần mềm bị chậm đi. Cơ chế này thường hay tạo rất nhiều đối tượng tạm (temporary object) và khi đó cơ chế dọn rác Garbage Collection của Java sẽ hoạt động và tốn tài nguyên máy tính.
PARCELABLE - ÔNG VUA TỐC ĐỘ
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 được tạo ra cải tiến từ Serializable, nó hiệu quả hơn và khắc phục được một số vấn đề tồn tại ở Java Serializable, đó là lý do tại sao đa phần lập trình viên Android ưu tiên sử dụng Parcelable hơn là Serializable.
Theo những gì mình đọc trên StackOverflow, hay theo các google engineers thì đoạn code trên sẽ chắc chắn 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 chương trình "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á phức tạp và làm cho những class này rất khó đọc và fix bug, bảo trì.
KẾT QUẢ 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,..
- Các object được test là HCMUSDeveloper và IceTeaVietDeveloper ở trên.
- 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) |
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.
TỔNG KẾT
Trong ví dụ trên, Android Parcelable tỏ ra nhanh hơn nhiều so với kỹ thuật Java Serializable. Một trong những lý do chính là do Parcelable hoàn toàn tùy chỉnh code, cho phép lập trình viên convert dữ liệu cần thiết thành Parcel trong khi Serialazation convert đối tượng thành một data stream sử dụng 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 object, 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 bạn cần dùng đến vị cứu tinh dành riêng cho lập trình viên Android - Parcelable.
________________________________________________________________________
Trên là những chia sẻ của mình về hai hướng tiếp cận cho việc truyền object ref. Cảm ơn các bạn đã theo dõi, chúc các bạn học tốt và hãy để lại bình luận bên dưới nhé!
Bonus cho các bạn 1 tấm hình từ slide của anh Huynh Q. Thao về những tip trong Android Perfomance, đó cũng là lý do và động lực để mình viết bài này :D
0 nhận xét:
Đăng nhận xét