Android

Thư viện framework và thư viện support trong Android (Bài 2)

Trong bài viết trước, chúng tôi đã đưa ra điểm khác biệt cơ bản nhất giữa thư viện framework và thư viện support. Trong bài viết này, chúng tôi sẽ nói chi tiết hơn về thư viện support nhằm giúp các bạn hiểu thêm về thư viện này, đặc biệt là tầm quan trọng của nó.

android-design-support-library

[Bài viết bao gồm một số từ tiếng Anh và tôi xin phép không dịch sang tiếng Việt mà để nguyên từ, vì trong Việt chỉ có các từ gần nghĩa so với các từ gốc kia. Việc thay từ tiếng Việt có thể sẽ làm mất nghĩa của từ gốc.]

Trước khi đọc tiếp, các bạn hãy nhớ lại ví dụ “hậu cần” mà tôi đã nói trong bài viết trước. Bạn có 2 phương án: hoặc là “tới đó rồi tính” , hoặc là chuẩn bị sẵn thức ăn và nước uống để đem theo. Nếu bạn chọn cách thứ nhất, thì tương tự như bạn đang phụ thuộc vào thư viện framework. Còn nếu bạn chọn cách thứ hai, thì cũng giống như bạn đang tích hợp thư viện support vào Android project của bạn vậy.

Thư viện support có thể hiểu ngắn gọn, là một biến thể của thư viện framework nhằm hỗ trợ các phiên bản khác nhau của Android. Đây là một nước đi rất hay của Google nhằm hạn chế khó khăn cho các lập trình viên khi viết ứng dụng cho Android vốn là một hệ điều hành có độ phân mảnh rất cao, cả về chiều sâu lẫn chiều rộng: Có quá nhiều phiên bản Android khác nhau vẫn đang được sử dụng bởi người dùng, từ các phiên bản build khác nhau do thời gian (Android 4.1 – 7.1) đến các bản build khác nhau do nhà sản xuất (Samsung, LG, HTC, Sony…). Nó giúp bạn support (hỗ trợ) các phiên bản Android khác nhau.

Để minh họa, tôi có một ví dụ đơn giản như sau: Tôi đang định viết một ứng dụng, trong đó sử dụng 1 ActionBar để chứa tên ứng dụng cũng như chứa các nút hành động, có thể chạy từ API 9 trở về sau này. Tuy nhiên, class android.app.ActionBar yêu cầu Api mức 11 trở về sau. Nếu bạn cố tình, bằng một cách nào đó, ép cái IDE của bạn build ra file APK và bạn đem cài đặt lên một thiết bị đang vẫn còn chạy Android 2.3, nó sẽ đưa ra thông báo dừng quen thuộc. Lí do rất đơn giản, Android đang muốn nói “Tôi là Android 2.3 và tôi không có bất kì class nào tên ActionBar thì làm sao tôi thực thi được?”. Tình huống giống như bạn đi hỏi một đứa học sinh lớp 5 rằng đạo hàm của hàm số y = lnx là gì.

Một ví dụ khác là các phiên bản Android trên các máy của các hãng sản xuất khác nhau có thể khác nhau, cho dù là chúng đang cùng mang một số hiệu Android, thậm chí là cùng số build. Tình huống không khác gì tô bún bò ở các tiệm bán khác nhau thì ăn có vị khác nhau, mặc dù chúng cùng giá tiền. Android là một hệ điều hành cho phép tùy biến cao, và các nhà sản xuất đương nhiên phải thêm thắt những hàm, những tính năng đặc trưng riêng để câu khách, và đôi khi các hàm của họ có thể gây ảnh hưởng tới các hàm khác của Android do Google viết, và dẫn tới tình trạng bạn build ứng dụng ra, máy này chạy ngon cơm, máy kia chạy ngọt canh, nhưng tới máy nọ thì chạy không ổn hoặc thậm chí, có thể bị dừng.

Quay lại ví dụ “hậu cần”. Giả sử nhóm của bạn, có một người nhất quyết chỉ ăn bánh bao, trong khi bạn chưa biết ở nơi đó có bán bánh bao hay không. Không lẽ bạn đánh cược? Nhưng lỡ đó là một ai đó rất quan trọng, không chiều không được thì sao??????? Cách tốt nhất: Chuẩn bị sẵn bánh bao. Mặc kệ ở nơi đó có ai bán hay không. Có cũng được, không có cũng không sao. Tôi đây đã có sẵn rồi. Và điều này tương tự như việc bạn sẽ dùng thư viện support để viết code cho ứng dụng của mình. Mặc kệ cái hệ điều hành host là Android 2.3 hay 7.1 có hỗ trợ class này, hàm kia hay không, kệ cái thiết bị đó là điện thoại Samsung Galaxy hay máy tính bảng LG G Pad, nội bộ ứng dụng của tôi đã có đủ định nghĩa cho các lớp, các hàm tôi cần thì tới khi thực thi, nó chỉ cần “móc tiền túi” ra mà dùng. Và đó chính là ưu điểm nổi bật của thư viện support.

Tới đây thì bạn có thể hiểu được một phần bản chất của thư viện support. Nó chẳng qua là tập hợp các class được resemble theo các class framework, ví dụ android.app.AlertDialog và android.support.v7.app.AlertDialog, nhằm support các phiên bản Android khác nhau bằng cách cho tích hợp nội bộ trong ứng dụng của bạn, cung cấp các hàm thực hiện các thao tác cho ra kết quả tương tự như các hàm trong các class framework vậy, làm cho ứng dụng của bạn có thể mang một tính năng nào đó, vốn chỉ khả dụng trên một phiên bản Android cao hơn, xuống các phiên bản Android thấp hơn, bất kể nhà sản xuất thiết bị đó là ai. Qua đó, ứng dụng của bạn tiếp cận được nhiều người dùng hơn. Chẳng hạn, bạn đang viết một app với giao diện Material Design vốn được Google công bố cùng lúc với Android 5.0, xin lỗi, đúng hơn là L Preview, nhưng chạy được trên các phiên bản Android 4 đó sao?

Một số thư viện support có thể giúp bạn dễ thở hơn trong việc viết code, mặc dù bạn có thể không cần dùng tới chúng vì bản thân ứng dụng không đòi support class kia, chẳng hạn như ContextCompat. Từ Android 6.0 Marshmallow trở về sau, Google yêu cầu ứng dụng của bạn phải yêu cầu các quyền nguy hiểm (nguyên văn: dangerous permissions) khi ứng dụng được thực thi (runtime permissions), mặc dù chúng sẽ được tự động cấp quyền trên các phiên bản cũ hơn. Và bạn sẽ phải hát khúc hát này:

Trong đó, hàm Context#checkSelfPermission(String permission) yêu cầu Api 23, tức Android M, hay 6.0 Marshmallow về sau, do đó lúc nào bạn cũng phải đặt toàn bộ khối lệnh vào thân hàm if (…) như sau, và đặt ở phương thức life cycle nào là tùy vào ý bạn:

Tuy nhiên, nếu bạn dùng nhiều permissions khác nhau và có khi phải kiểm tra liên tục, vì lỡ người dùng nhấn nhầm nên không cấp phép cho ứng dụng của bạn, thì nó sẽ dừng hoặc tệ hơn nữa là chạy sai! Và có khi bạn phải dùng cái if (…) kia tới… chục lần. Buổi sáng thì đỡ, bạn đang code vào buổi chiều mệt mỏi thì dễ gây ức chế, và tệ hơn hết là sẽ gây ra thêm lỗi và không biết sửa sao. Vì vậy, bạn có thể dùng ContextCompat#checkSelfPermission(Context context, String permission). Nó sẽ đỡ gây phiền phức cho bạn nhiều vì bản thân nó đã có code xử lí các trường hợp gây ức chế kia.

Mặt khác, có nhiều thư viện, cụ thể hơn là các thành phần giao diện, chỉ có trong thư viện support mà không có trong thư viện framework của bất kì phiên bản Android nào, ví dụ: RecyclerView và CardView. Bạn không thể tìm các class tương ứng trong thư viện framework, bất kể là mức Api nào. Và do đó, nếu bạn muốn sử dụng RecyclerView hay CardView, bạn chỉ có một cách duy nhất là yêu cầu compile thêm các thư viện kia trong tập tin build.gradle.

Đến đây, chúng tôi mong rằng bạn đã hiểu được vì sao đội phát triển Android tại Google lại làm ra hệ thống thư viện support để làm gì. Tóm lại, chỉ có 2 ý như sau:

  • Để hỗ trợ các phiên bản Android khác nhau: Giúp lập trình viên có thể đem các tính năng xuống tương thích với nhiều phiên bản Android nhất có thể, mà nếu chỉ rely vào thư viện framework thì chỉ có thể chạy trên các bản Android mới, cũng như giảm bớt gánh nặng cho lập trình viên khi phải viết đi viết lại các code phức tạp cho các phiên bản Android khác nhau.
  • Dễ cập nhật, điều chỉnh hơn, đặc biệt là các class không bắt buộc bản thân Android phải hỗ trợ.

Hẹn gặp lại các bạn trong bài tiếp theo.

4 thoughts on “Thư viện framework và thư viện support trong Android (Bài 2)”

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.