1. Introduction
Navigation Architecture Component đơn giản hoá điều hướng trong ứng dụng của bạn, giúp bạn hình dung được luồng chạy của ứng dụng một cách trực quan nhất. Thư viện này cung cấp một số chức năng như:
- Tự động xử lý fragment transactions
- Xử lý animations and transitions
- Xử lý Deep linking
- Triển khai các navigation UI patterns (như drawers and bottom nav) đơn giản hơn.
- Type safety (Chuyển dữ liệu giữa các màn hình an toàn hơn)
- Cung cấp công cụ edit create flow trực quan.
2. What you’ll build
Ở bài viết này mình chỉ đề cập đến các chức năng gồm :
– Cách tạo và sử dụng Navigation Component cơ bản
– Sử dụng Type safety trong việc truyền dữ liệu.
3. Build
B1. cReate project
– Project này mình sẽ sử dụng Kotlin để demo, các bạn vẫn tạo project như bình thường và tick vào kotlin lúc khởi tạo.
– Thêm thư viện navigation vào build.gradle.
def nav_version = "2.1.0-rc01"
implementation 'androidx.core:core-ktx:1.0.2'
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
Về cơ chế navigation component chỉ sử dụng 1 activity_main và các màn hình con sẽ là các fragment. Để tạo flow và sử dụng chúng ta sẽ nhúng một NavHostFragment vào activity_main.xml bằng 2 step sau:
Step 1: Tạo nav_graph.xml
Click nào res/Android Resource File và tạo như hình dưới với type navigation.
Step 2: Nhúng nav_graph vào activity_main.xml
<fragment android:id="@+id/nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:defaultNavHost="true" app:navGraph="@navigation/nav_graph" />
Bây giờ cơ bản là chúng ta đã config xong Navigation với Host là activity_main.
b2. tạo các màn hình con và flow.
Bây giờ chúng ta sẽ quay lại nav_graph.xml để tạo giao diện và flow.
Ở đây mình tạo 1 flow đơn giản như trên, về cách tạo qua 2 bước sau.
Tiếp theo để tạo các action chuyển đổi màn hình, chỉ cần click chuột và kéo vào các màn hình muốn mở, android studio sẽ tự động tạo ra code.
<fragment android:id="@+id/splashFragment" android:name="com.android.navigation_component_example.SplashFragment" android:label="Splash" tools:layout="@layout/fragment_splash" > <action android:id="@+id/action_splash_to_login" app:destination="@id/loginFragment" app:popUpTo="@+id/splashFragment" app:popUpToInclusive="true"/> </fragment>
- action_splash_to_login : Khi gọi hàm này sẽ mở màn hình LoginFragment
- Thông thường thì Splash sẽ mất đi bạn sẽ cần phải xoá nó khỏi stack bằng cách thêm 2 dòng :
app:popUpTo="@+id/splashFragment"
app:popUpToInclusive="true"
Giờ thì gọi hàm sử dụng thôi 😀
class SplashFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_splash, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Handler().postDelayed({
Navigation.findNavController(view).navigate(R.id.action_splash_to_login)
}, 2000)
}
}
Tương tự tạo tiếp các màn hình Login/Main/Detail các button để mở màn hình như flow hoàn chỉnh ở hình đầu.
B3. sử dụng type safety
Để sử dụng thì chúng ta cần thêm các thư viện phụ thuộc vào build.gradle top.
def nav_version = "2.1.0-rc01"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
Mở tiếp build.gradle app thêm.
apply plugin: "androidx.navigation.safeargs.kotlin"
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
// For Kotlin projects
kotlinOptions {
jvmTarget = "1.8"
}
Lưu ý tích hợp JAVA-8 vào nhé (ahihi đồ ngốc =)) tiến hành Sync Project
Plugin này sẽ auto genarate code khi chúng ta update ở nav_graph.xml công việc chỉ cần click Sync mỗi khi thay đổi là đc. (omg xịn xò dị sao =)) )
Tiếp theo mình sẽ demo chuyển dữ liệu 2 loại.
– Basic Types
– Object
Ở HomeFragment mình sẽ yêu cầu tham số nhận được có tên myArg kiểu bất kỳ, bằng cách thêm argument như bên dưới sau đó bấm Sync.
<fragment android:id="@+id/loginFragment" android:name="com.android.navigation_component_example.LoginFragment" android:label="Login" tools:layout="@layout/fragment_login" > <action android:id="@+id/action_login_to_home" app:destination="@id/homeFragment" app:popUpTo="@+id/loginFragment" app:popUpToInclusive="true"/> </fragment> <fragment android:id="@+id/homeFragment" android:name="com.android.navigation_component_example.HomeFragment" android:label="Home" tools:layout="@layout/fragment_home" > <action android:id="@+id/action_home_to_detail" app:destination="@id/detailFragment" /> <argument android:name="myArg" android:defaultValue="0" /> </fragment>
Sau đó bấm Sync để genarate ra code.
Tiếp theo chúng ta viết code để từ LoginFragment mở HomeFragment và truyền thêm giá trị vào.
btnLogin.setOnClickListener {
if (edtInputValue.text.toString().isNotEmpty()) {
val value = edtInputValue.text.toString().toInt()
val action = LoginFragmentDirections.actionLoginToHome(value)
it.findNavController().navigate(action)
}
}
LoginFragmentDirections.java có được khi Sync Project
Ở HomeFragment lấy giá trị bằng cách gọi.
val safeArgs: HomeFragmentArgs by navArgs()
val value = safeArgs.myArg
HomeFragmentArgs.java có được khi Sync Project
Cơ bản thư viện Safe sẽ sử dụng code ở nav_graph.xml để genarate ra các file cấu trúc sẵn, việc cần làm chỉ gọi ra để dùng thôi 😀
Okay ở trên là truyền dữ liệu kiểu basic, vậy mình muốn truyền 1 object thì như thế nào ??
Đầu tiên mình tạo 1 Model: User.kt
data class User(var userName: String) : Serializable
Ở Trên mình đã từ Login –> Home rồi.
Giờ mình sẽ tạo 1 cái từ Home –> Detail và truyền User.kt từ Home sang.
Sau khi tạo Model User.kt rồi thì mình sẽ thêm Fragment mới là DetailFragment.kt và đưa nó vào nav_graph.xml. Ở đây mình sẽ yêu cầu tham số truyền vào là 1 Object User.
<fragment android:id="@+id/detailFragment" android:name="com.android.navigation_component_example.DetailFragment" android:label="Detail" tools:layout="@layout/fragment_detail"> <argument android:name="userArg" app:argType="com.android.navigation_component_example.model.User" app:nullable="true" android:defaultValue="@null" /> </fragment>
Các bạn lưu ý ở đây app:argType phải đúng đường dẫn tới model luôn nhé.
Oke bước tiếp theo cũng bấm Sync để genarate ra code.
Cách sử dụng cũng tương tự kiểu basic type thôi.
Ở HomeFragment.kt truyền đi
Nhận ở DetailFragment.kt.
btnOpenDetail.setOnClickListener {
if (edtInputValue.text.toString().isNotEmpty()) {
val user = User(edtInputValue.text.toString())
val action = HomeFragmentDirections.actionHomeToDetail(user)
it.findNavController().navigate(action)
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val safeArgs : DetailFragmentArgs by navArgs()
val user : User = safeArgs.userArg as User
tvReceiveValue.text = "Value Receive:\n" + user.toString()
}
Yep, Cơm ngon canh ngọt thì build là chạy luôn nha =)))
Vậy ở bài viết này mình đã giới thiệu sơ qua cho các bạn về cách tạo và sử dụng Navigation Component rồi.
Còn khá nhiều thứ hay ho như animation, deeplink, trong quá trình làm việc chúng ta có thể tìm hiểu thêm.
Về cơ bản đây là một thư viện vô cùng tuyệt vời.
Github tham khảo.