Chào mừng các bạn đến với chủ đề về Android Jetpack.
Lại một chủ đề nữa của Jetpack được chúng ta mang ra mổ xẻ, để hiểu và sử dụng thành thạo công năng của nó. Và cái tên hôm nay được nhắc đến chính là Navigation.
Thực tế thì khối lượng kiến thức về Navigation này khá là nhiều, và lợi ích mà thư viện này mang lại nó cũng nhiều như độ lớn của kiến thức này vậy. Thư viện này giúp chúng ta xây dựng các màn hình của ứng dụng, cụ thể là việc bố trí các Fragment, sắp xếp chúng, tạo cho chúng sự tương tác, các kịch bản tới/lui giữa chúng, một cách dễ dàng và trực quan hơn với cách cũ trước đây. Và mình cũng cá một điều rằng rất nhiều bạn cũng đã nhanh chóng làm quen và nắm được cách thức vận dụng Navigation này rồi. Bài viết hôm nay của mình sẽ cố gắng mang đến cái nhìn ban đầu về loại thư viện này, sẽ có các phần sau nữa sẽ là các phần mà chúng ta cùng nhau xây dựng một ứng dụng đơn giản, rồi nâng cấp với việc sử dụng sâu hơn các công cụ hỗ trợ khác của thư viện.
Giới Thiệu Navigation
Bạn có thể xem thông tin giới thiệu về Navigation dưới đây.
Để nói về Navigation, thì điều đầu tiên chúng ta cần mang ra bàn luận, đó là “triết lý thiết kế ứng dụng Android”.
Chà, nói đến triết lý, thì cũng mệt với ông Android này. Thật vậy, một khi bạn theo đuổi nền tảng này một thời gian khá lâu, hoặc khi bạn tạm thời không còn làm Android nữa, đột nhiên một ngày nọ bạn vào trang chính Developer của Android, bạn sẽ thấy mọi thứ thay đổi, như thể bạn vừa bị tẩy não vậy, lạ lẫm và mò mẫm như ngày mới tiếp cận.
Ở những ngày đầu khi thiết kế ứng dụng Android, bạn được giới thiệu rằng một ứng dụng nên có nhiều Activity. Mỗi Activity là một màn hình độc lập. Thời điểm này hễ cần thiết thì chúng ta cứ tạo một Activity cho một màn hình mới. Màn hình đứng và ngang là những Activity khác nhau. Điều chúng ta quan tâm hơn nữa là đường đi giữa các Activity, Activity nào sẽ start Activity nào, khi một Activity kết thúc thì nó sẽ trở về Activity nào. Rồi cả việc trao đổi dữ liệu giữa các Activity với nhau nữa.
Về sau, đùng một phát chúng ta được Google giới thiệu đến Fragment. Và triết lý thiết kế ứng dụng cũng từ đó thay đổi theo. Thay vì tập trung vào việc tạo ra nhiều Activity. Các ứng dụng Android khi này được khuyến cáo là nên “tiết kiệm” Activity lại. Một ứng dụng chỉ cần thậm chí một Activity. Các màn hình lúc này cũng được các Fragment đảm nhiệm. Một Activity đang sống có khả năng thêm vào/thay thế/gỡ bỏ các Fragment cho phù hợp với ngữ cảnh của ứng dụng. Thậm chí với các màn hình xoay ngang hay dọc cũng chỉ là các thay đổi về Fragment. Việc trao đổi dữ liệu lúc bấy giờ có phần dễ thở hơn do bản thân các Activity sẽ sống lâu hơn và đảm nhiệm vai trò truyền đạt dữ liệu giữa các Fragment mà nó nắm giữ với nhau.
Rồi về sau nữa. À không, bây giờ. Jetpack ra đời. Cung cấp một vài thư viện cao cấp trong bộ Architecture Component, giúp cho việc quản lý về dữ liệu giữa các Fragment được dễ thở và thậm chí có phần tuyệt vời hơn các cách cũ trước đây, có thể kể ra đây như ViewModel và LiveData. Chưa dừng lại ở sự hỗ trợ về mặt dữ liệu, Jetpack còn mang đến một thư viện mới mẻ có cái tên Navigation. Từ đây, chúng ta có thể dễ dàng nắm bắt, điều khiển đường đi của các Fragment. Chúng ta quản lý được một kịch bản đường đi của các Fragment, biết chúng bắt đầu từ Fragment nào, đi tiếp qua Fragment nào, kết thúc ở Fragment nào,… một cách trực quan bằng giao diện.
Triết lý thiết kế ứng dụng Android như bạn thấy là thay đổi rất nhanh. Mặc dù việc thay đổi luôn khiến chúng ta lại phải lao vào học hỏi và tìm hiểu chúng. Nhưng rõ ràng lợi ích mà chúng mang lại là rất lớn, và việc tiếp cận chúng cũng khá thú vị đúng không nào (vi vọng các bạn cũng đang cảm thấy vậy). Vậy hãy xem Jetpack với Navigation sẽ thay đổi cách chúng ta thiết kế ứng dụng như thế nào ở mục tiếp theo nhé.
Lợi Ích Của Navigation
Có lẽ bạn đã biết được lợi ích của Navigation này thông qua mục trên đây rồi. Nhưng đó là nói sơ qua thôi. Có thể liệt kê các lợi ích của Navigation ở đây, bạn hãy từ từ làm quen và trải nghiệm.
- Dĩ nhiên lợi ích đầu tiên là giúp bạn có một công cụ quản lý các tương tác giữa các Fragment rồi.
- Nhưng nhờ có sự trợ giúp của công cụ này mà bạn còn được “miễn phí” luôn các xử lý của việc nhấn back của người dùng (ngày xưa hệ thống cũng căn cứ vào back stack để giúp chúng ta rồi nhưng nhờ Navigation mà nay việc back này sẽ hợp lý hơn).
- Chúng ta còn có các resource cũng như các chuyển động theo chuẩn Android nữa.
- Một điều khá hay là Navigation này cũng sẽ hỗ trợ tốt cho deep linking.
- Chúng ta có sẵn Navigation UI, thành phần này giúp Navigation có thể làm việc tốt với các thể loại giao diện được xây dựng sẵn như Toolbar, Navigation Drawers hay Bottom Navigation.
- Được hỗ trợ Safe Args giúp truyền dữ liệu qua các thành phần bên trong Navigation được an toàn hơn.
- Có được sự cộng tác tốt với ViewModel.
Các Thành Phần Của Navigation
Mình biết, thật sớm khi nói đến các thành phần của Navigation trong khi chưa biết cách thức hoạt động và quản lý của nó ra sao. Lúc mới làm quen Navigation mình cũng đã rất đau đầu ở mục này, đọc đi đọc lại hoài mà không hiểu bao nhiêu. Nhưng mình thấy các tài liệu đều nói trước vậy đó, bạn cứ đọc trước đi, sau này khi biết Navigation là gì rồi thì bạn hãy xem lại xem có hiểu nhiều hơn không nhé.
Navigation được chia làm 3 phần.
Navigation Graph
Đây là một resource XML mới mà Android đã định nghĩa ra, nó giúp Android Studio vẽ lên một mô hình các màn hình. Mỗi một màn hình này được gọi với cái tên khá rõ ràng là destination. Các destination này có thể được liên kết với nhau bởi các action, mỗi action như vậy có thể cho chúng ta thông tin về đường đi trực quan giữa các destination với nhau.
Bạn hãy xem một Navigation Graph của một ứng dụng có 6 destination và 5 action được mình lấy từ trang hướng dẫn của Google.
Bạn có thể thấy số 1 ở trên hình chính là một destination của Navigation Graph. Còn số 2 là action nối giữa hai destination rồi đúng không nào. Mục này mang tính chất giới thiệu cho bạn biết Navigation Graph là gì thôi nhé. Cách thức tạo resource dạng này, chi tiết và cách tương tác với nó như thế nào mình sẽ nói cụ thể hơn ở phần sau.
NavHost
Google viết sao mình viết y vậy, thực ra viết cho đầy đủ chữ trên là Navigation Host. NavHost là một không gian trên màn hình để chứa từng destination bên trong Navigation Graph trên kia. Vậy bạn có thể hiểu, Navigation Graph giúp tạo ra một sơ đồ, hay kịch bản mà người dùng sẽ đi qua theo từng destination bởi action. Rồi từng destination đó phải cần một nơi để hiển thị lên trên màn hình, nơi đó chính là NavHost này đây.
Khi thiết kế ra thư viện Navigation này. Google muốn Activity sẽ là nơi chứa NavHost. Như vậy mỗi một Activity sẽ bao gồm một tập hợp nhiều màn hình con được biểu diễn trong Navigation Graph. Nếu bạn xây dựng một ứng dụng gồm nhiều Activity, bạn có thể có nhiều NavHost trong từng Activity đó.
Chúng ta cũng sẽ xem cách tạo một NavHost sau. Giờ đế thành phần cơ bản kế tiếp.
NavController
Một đối tượng được xây dựng ra để giúp chúng ta điều khiển việc qua lại giữa các destination bên trong NavHost. Bởi vì dù có Navigation Graph giúp diễn đạt các destination lẫn action, có NavHost để hiển thị destination nào lên màn hình rồi, nhưng không có các dòng lệnh giúp thực thi các thay đổi hiển thị này thì không được, và NavController cung cấp cho chúng ta các công cụ để làm chuyện đó.
Xây Dựng Ứng Dụng
Phần trên đây khá nặng về lý thuyết, chính vì vậy mình sẽ mang đến cho các bạn một ứng dụng Android với một chức năng cơ bản mà hầu hết các ứng dụng khác đều có, đó là chức năng đăng nhập. Dĩ nhiên đã gọi là đăng nhập thì cũng bao gồm đăng ký và đăng xuất luôn đấy nhé.
Dưới đây là mô phỏng việc sử dụng ứng dụng này, cho các bạn có cái nhìn ban đầu về nó.
Để xây dựng các màn hình trên, mình đã dựng nên một Navigation Graph như thế này.
Kịch bản là khi người dùng mở ứng dụng lên, homeFragment sẽ được hiển thị đầu tiên. Tuy nhiên nếu người dùng chưa đăng nhập, ứng dụng sẽ dẫn thẳng vào màn hình signInFragment, tại đây nếu người dùng chưa có account thì có thể vào signUpFragment để tạo rồi quay lại đăng nhập với signInFragment. Sau khi đăng nhập thành công, ở những lần mở ứng dụng sau đó, người dùng sẽ thấy được màn hình homeFragment, từ đây có thể vào được profileFragment. Nếu ở profileFragment mà người dùng nhấn nút Logout, ứng dụng sẽ đăng xuất và (một cách tự động) signInFragment sẽ lại được hiển thị.
Về kỹ thuật, mình không có dùng gì cao siêu cả. Ứng dụng sẽ không có Social login. ViewModel và LiveData được dùng ở mức đơn giản đủ để chạy logic. Dữ liệu người dùng được lưu trực tiếp trên thiết bị nhưng không lưu với SQLite Database hoành tráng mà chỉ lưu theo dạng key-value vào SharedPreferences mà thôi. Mình chỉ tập trung nhất có thể vào Navigation, nhằm giúp cho các bạn có một cái nhìn tốt nhất về thư viện này của Jetpack.
Và chúng ta sẽ bắt đầu xây dựng ứng dụng này ở các phần sau. Hẹn gặp lại các bạn.
Kết Luận
Chúng ta vừa đi qua phần 1 và cùng nhau tìm hiểu sơ về các khái niệm của thư viện Navigation của Jetpack này. Ở bài sau chúng ta sẽ cùng nhau xây dựng nên những thứ mà bài viết hôm nay nhắc đến. Bạn sẽ hiểu rõ hơn về chúng và cách sử dụng chúng như thế nào trong việc xây dựng một ứng dụng một cách dễ dàng hơn nhé.
Cảm ơn bạn đã đọc các bài viết của Yellow Code Books. Bạn hãy ủng hộ blog bằng cách:
– Đánh giá 5 sao ở mỗi bài viết nếu thấy thích.
– Comment bên dưới mỗi bài viết nếu có thắc mắc.
– Để lại địa chỉ email của bạn ở thanh bên phải để nhận được thông báo sớm nhất khi có bài viết mới.
– Chia sẻ các bài viết của Yellow Code Books đến nhiều người khác.
– Ủng hộ blog theo hướng dẫn ở thanh bên phải để blog ngày càng phát triển hơn.
Tuyệt quá cuối cùng anh cũng ra bài mới