Kiến thức cơ bản về Kotlin cho Android 06.3: Sử dụng LiveData để kiểm soát trạng thái của nút

Lớp học lập trình này thuộc khoá học Kiến thức cơ bản về Kotlin cho Android. Bạn sẽ nhận được nhiều giá trị nhất qua khoá học này nếu thực hiện các lớp học lập trình theo trình tự. Tất cả lớp học lập trình của khoá học đều được liệt kê trên trang đích của lớp học lập trình Kiến thức cơ bản về cách tạo ứng dụng Android bằng Kotlin.

Giới thiệu

Lớp học lập trình này tóm tắt cách sử dụng kết hợp ViewModel và các mảnh để triển khai hoạt động điều hướng. Hãy nhớ rằng mục tiêu là đặt logic của when để điều hướng vào ViewModel, nhưng hãy xác định các đường dẫn trong các mảnh và tệp điều hướng. Để đạt được mục tiêu này, bạn sẽ sử dụng các mô hình khung hiển thị, mảnh, LiveData và các đối tượng theo dõi.

Phần hướng dẫn này kết thúc bằng cách cho thấy một cách thông minh để theo dõi trạng thái nút với mã tối thiểu, sao cho mỗi nút chỉ được bật và có thể nhấp vào khi người dùng có thể nhấn vào nút đó.

Kiến thức bạn cần có

Bạn cần thông thạo:

  • Xây dựng giao diện người dùng (UI) cơ bản bằng cách sử dụng một hoạt động, các mảnh và khung hiển thị.
  • Điều hướng giữa các mảnh và sử dụng safeArgs để truyền dữ liệu giữa các mảnh.
  • Xem các mô hình, nhà máy mô hình hiển thị, các phép biến đổi và LiveData cũng như các đối tượng theo dõi của chúng.
  • Cách tạo cơ sở dữ liệu Room, tạo đối tượng truy cập dữ liệu (DAO) và xác định các thực thể.
  • Cách sử dụng coroutine cho các lượt tương tác với cơ sở dữ liệu và các tác vụ chạy trong thời gian dài khác.

Kiến thức bạn sẽ học được

  • Cách cập nhật bản ghi hiện có về chất lượng giấc ngủ trong cơ sở dữ liệu.
  • Cách sử dụng LiveData để theo dõi trạng thái của nút.
  • Cách hiển thị một thanh thông báo nhanh để phản hồi một sự kiện.

Bạn sẽ thực hiện

  • Mở rộng ứng dụng TrackMySleepQuality để thu thập điểm xếp hạng chất lượng, thêm điểm xếp hạng vào cơ sở dữ liệu và hiển thị kết quả.
  • Sử dụng LiveData để kích hoạt việc hiển thị một thanh thông báo nhanh.
  • Sử dụng LiveData để bật và tắt các nút.

Trong lớp học lập trình này, bạn sẽ tạo bản ghi chất lượng giấc ngủ và giao diện người dùng hoàn chỉnh của ứng dụng TrackMySleepQuality.

Ứng dụng này có 2 màn hình, được biểu thị bằng các mảnh, như minh hoạ trong hình bên dưới.

Màn hình đầu tiên (xuất hiện ở bên trái) có các nút để bắt đầu và dừng theo dõi. Màn hình này cho thấy tất cả dữ liệu về giấc ngủ của người dùng. Nút Xoá sẽ xoá vĩnh viễn tất cả dữ liệu mà ứng dụng đã thu thập cho người dùng.

Màn hình thứ hai (ở bên phải) là màn hình chọn mức đánh giá chất lượng giấc ngủ. Trong ứng dụng, điểm xếp hạng được biểu thị bằng số. Để phục vụ mục đích phát triển, ứng dụng này cho thấy cả biểu tượng khuôn mặt và giá trị tương đương bằng số của biểu tượng đó.

Luồng người dùng như sau:

  • Người dùng mở ứng dụng và thấy màn hình theo dõi giấc ngủ.
  • Người dùng nhấn vào nút Bắt đầu. Thao tác này sẽ ghi lại thời gian bắt đầu và hiển thị thời gian đó. Nút Start (Bắt đầu) bị vô hiệu hoá và nút Stop (Dừng) được bật.
  • Người dùng nhấn vào nút Dừng. Thao tác này sẽ ghi lại thời gian kết thúc và mở màn hình chất lượng giấc ngủ.
  • Người dùng chọn một biểu tượng chất lượng giấc ngủ. Màn hình đóng lại và màn hình theo dõi sẽ hiển thị thời gian kết thúc giấc ngủ và chất lượng giấc ngủ. Nút Stop (Dừng) bị tắt và nút Start (Bắt đầu) được bật. Ứng dụng đã sẵn sàng cho một đêm khác.
  • Nút Xoá sẽ bật bất cứ khi nào có dữ liệu trong cơ sở dữ liệu. Khi người dùng nhấn vào nút Xoá, tất cả dữ liệu của họ sẽ bị xoá mà không có cách nào khôi phục được. Không có thông báo "Bạn có chắc chắn không?".

Ứng dụng này sử dụng một cấu trúc đơn giản, như minh hoạ dưới đây trong bối cảnh của cấu trúc đầy đủ. Ứng dụng chỉ sử dụng các thành phần sau:

  • Bộ điều khiển giao diện người dùng
  • Xem mô hình và LiveData
  • Cơ sở dữ liệu Room

Lớp học lập trình này giả định rằng bạn biết cách triển khai hoạt động điều hướng bằng cách sử dụng các mảnh và tệp điều hướng. Để giúp bạn tiết kiệm công sức, chúng tôi đã cung cấp một phần lớn mã này.

Bước 1: Kiểm tra mã

  1. Để bắt đầu, hãy tiếp tục với mã của riêng bạn từ cuối lớp học lập trình trước hoặc tải mã khởi đầu xuống.
  2. Trong mã khởi đầu, hãy kiểm tra SleepQualityFragment. Lớp này mở rộng bố cục, lấy ứng dụng và trả về binding.root.
  3. Mở navigation.xml trong trình chỉnh sửa thiết kế. Bạn thấy rằng có một đường dẫn điều hướng từ SleepTrackerFragment đến SleepQualityFragment và quay lại từ SleepQualityFragment đến SleepTrackerFragment.



  4. Kiểm tra mã cho navigation.xml. Cụ thể, hãy tìm <argument> có tên là sleepNightKey.

    Khi người dùng chuyển từ SleepTrackerFragment sang SleepQualityFragment,, ứng dụng sẽ truyền một sleepNightKey đến SleepQualityFragment cho đêm cần được cập nhật.

Bước 2: Thêm chế độ điều hướng để theo dõi chất lượng giấc ngủ

Biểu đồ điều hướng đã bao gồm các đường dẫn từ SleepTrackerFragment đến SleepQualityFragment và ngược lại. Tuy nhiên, các trình xử lý lượt nhấp triển khai thao tác điều hướng từ một mảnh sang mảnh tiếp theo vẫn chưa được mã hoá. Bây giờ, bạn sẽ thêm mã đó vào ViewModel.

Trong trình xử lý lượt nhấp, bạn đặt một LiveData sẽ thay đổi khi bạn muốn ứng dụng chuyển đến một đích đến khác. Mảnh này theo dõi LiveData. Khi dữ liệu thay đổi, mảnh sẽ chuyển đến đích đến và cho mô hình hiển thị biết rằng thao tác đã hoàn tất, thao tác này sẽ đặt lại biến trạng thái.

  1. Mở SleepTrackerViewModel. Bạn cần thêm chế độ điều hướng để khi người dùng nhấn vào nút Dừng, ứng dụng sẽ chuyển đến SleepQualityFragment để thu thập điểm chất lượng.
  2. Trong SleepTrackerViewModel, hãy tạo một LiveData thay đổi khi bạn muốn ứng dụng chuyển đến SleepQualityFragment. Sử dụng tính năng đóng gói để chỉ hiển thị phiên bản có thể nhận của LiveData cho ViewModel.

    Bạn có thể đặt mã này ở bất kỳ vị trí nào ở cấp cao nhất của nội dung lớp.
private val _navigateToSleepQuality = MutableLiveData<SleepNight>()

val navigateToSleepQuality: LiveData<SleepNight>
   get() = _navigateToSleepQuality
  1. Thêm hàm doneNavigating() để đặt lại biến kích hoạt thao tác điều hướng.
fun doneNavigating() {
   _navigateToSleepQuality.value = null
}
  1. Trong trình xử lý lượt nhấp cho nút Dừng, onStopTracking(), hãy kích hoạt thao tác điều hướng đến SleepQualityFragment. Đặt biến _navigateToSleepQuality ở cuối hàm làm mục cuối cùng bên trong khối launch{}. Xin lưu ý rằng biến này được đặt thành night. Khi biến này có giá trị, ứng dụng sẽ chuyển đến SleepQualityFragment, truyền theo đêm.
_navigateToSleepQuality.value = oldNight
  1. SleepTrackerFragment cần theo dõi navigateToSleepQuality để ứng dụng biết thời điểm điều hướng. Trong SleepTrackerFragment, trong onCreateView(), hãy thêm một đối tượng tiếp nhận dữ liệu cho navigateToSleepQuality(). Xin lưu ý rằng quy trình nhập cho thành phần này không rõ ràng và bạn cần nhập androidx.lifecycle.Observer.
sleepTrackerViewModel.navigateToSleepQuality.observe(this, Observer {
})

  1. Bên trong khối trình quan sát, hãy điều hướng và truyền mã nhận dạng của đêm hiện tại, rồi gọi doneNavigating(). Nếu nội dung nhập của bạn không rõ ràng, hãy nhập androidx.navigation.fragment.findNavController.
night ->
night?.let {
   this.findNavController().navigate(
           SleepTrackerFragmentDirections
                   .actionSleepTrackerFragmentToSleepQualityFragment(night.nightId))
   sleepTrackerViewModel.doneNavigating()
}
  1. Tạo bản dựng và chạy ứng dụng của bạn. Nhấn vào Start (Bắt đầu), sau đó nhấn vào Stop (Dừng) để chuyển đến màn hình SleepQualityFragment. Để quay lại, hãy dùng nút Quay lại của hệ thống.

Trong nhiệm vụ này, bạn sẽ ghi lại chất lượng giấc ngủ và quay lại mảnh trình theo dõi giấc ngủ. Màn hình sẽ tự động cập nhật để cho người dùng thấy giá trị mới. Bạn cần tạo một ViewModel và một ViewModelFactory, đồng thời cần cập nhật SleepQualityFragment.

Bước 1: Tạo một ViewModel và một ViewModelFactory

  1. Trong gói sleepquality, hãy tạo hoặc mở SleepQualityViewModel.kt.
  2. Tạo một lớp SleepQualityViewModel nhận sleepNightKey và cơ sở dữ liệu làm đối số. Giống như đối với SleepTrackerViewModel, bạn cần truyền database từ nhà máy. Bạn cũng cần truyền sleepNightKey từ chế độ điều hướng.
class SleepQualityViewModel(
       private val sleepNightKey: Long = 0L,
       val database: SleepDatabaseDao) : ViewModel() {
}
  1. Bên trong lớp SleepQualityViewModel, hãy xác định JobuiScope, rồi ghi đè onCleared().
private val viewModelJob = Job()
private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)

override fun onCleared() {
   super.onCleared()
   viewModelJob.cancel()
}
  1. Để chuyển về SleepTrackerFragment bằng cách sử dụng cùng một mẫu như trên, hãy khai báo _navigateToSleepTracker. Triển khai navigateToSleepTrackerdoneNavigating().
private val _navigateToSleepTracker = MutableLiveData<Boolean?>()

val navigateToSleepTracker: LiveData<Boolean?>
   get() = _navigateToSleepTracker

fun doneNavigating() {
   _navigateToSleepTracker.value = null
}
  1. Tạo một trình xử lý lượt nhấp, onSetSleepQuality(), để sử dụng cho tất cả hình ảnh về chất lượng giấc ngủ.

    Sử dụng cùng một mẫu coroutine như trong lớp học lập trình trước:
  • Khởi chạy một coroutine trong uiScope và chuyển sang trình điều phối I/O.
  • Nhận tonight bằng sleepNightKey.
  • Đặt chất lượng giấc ngủ.
  • Cập nhật cơ sở dữ liệu.
  • Kích hoạt chế độ điều hướng.

Xin lưu ý rằng mẫu mã bên dưới thực hiện tất cả các thao tác trong trình xử lý lượt nhấp, thay vì tách thao tác cơ sở dữ liệu trong ngữ cảnh khác.

fun onSetSleepQuality(quality: Int) {
        uiScope.launch {
            // IO is a thread pool for running operations that access the disk, such as
            // our Room database.
            withContext(Dispatchers.IO) {
                val tonight = database.get(sleepNightKey) ?: return@withContext
                tonight.sleepQuality = quality
                database.update(tonight)
            }

            // Setting this state variable to true will alert the observer and trigger navigation.
            _navigateToSleepTracker.value = true
        }
    }
  1. Trong gói sleepquality, hãy tạo hoặc mở SleepQualityViewModelFactory.kt rồi thêm lớp SleepQualityViewModelFactory như minh hoạ bên dưới. Lớp này sử dụng một phiên bản của cùng một mã nguyên mẫu mà bạn đã từng thấy trước đây. Hãy kiểm tra mã trước khi chuyển sang bước tiếp theo.
class SleepQualityViewModelFactory(
       private val sleepNightKey: Long,
       private val dataSource: SleepDatabaseDao) : ViewModelProvider.Factory {
   @Suppress("unchecked_cast")
   override fun <T : ViewModel?> create(modelClass: Class<T>): T {
       if (modelClass.isAssignableFrom(SleepQualityViewModel::class.java)) {
           return SleepQualityViewModel(sleepNightKey, dataSource) as T
       }
       throw IllegalArgumentException("Unknown ViewModel class")
   }
}

Bước 2: Cập nhật SleepQualityFragment

  1. Mở SleepQualityFragment.kt.
  2. Trong onCreateView(), sau khi nhận được application, bạn cần lấy arguments đi kèm với chỉ đường. Các đối số này nằm trong SleepQualityFragmentArgs. Bạn cần trích xuất các tệp này khỏi gói.
val arguments = SleepQualityFragmentArgs.fromBundle(arguments!!)
  1. Tiếp theo, hãy lấy dataSource.
val dataSource = SleepDatabase.getInstance(application).sleepDatabaseDao
  1. Tạo một nhà máy, truyền dataSourcesleepNightKey vào.
val viewModelFactory = SleepQualityViewModelFactory(arguments.sleepNightKey, dataSource)
  1. Tạo một tham chiếu ViewModel.
val sleepQualityViewModel =
       ViewModelProviders.of(
               this, viewModelFactory).get(SleepQualityViewModel::class.java)
  1. Thêm ViewModel vào đối tượng liên kết. (Nếu bạn thấy lỗi với đối tượng liên kết, hãy tạm thời bỏ qua lỗi đó.)
binding.sleepQualityViewModel = sleepQualityViewModel
  1. Thêm đối tượng tiếp nhận dữ liệu. Khi được nhắc, hãy nhập androidx.lifecycle.Observer.
sleepQualityViewModel.navigateToSleepTracker.observe(this, Observer {
   if (it == true) { // Observed state is true.
       this.findNavController().navigate(
               SleepQualityFragmentDirections.actionSleepQualityFragmentToSleepTrackerFragment())
       sleepQualityViewModel.doneNavigating()
   }
})

Bước 3: Cập nhật tệp bố cục và chạy ứng dụng

  1. Mở tệp bố cục fragment_sleep_quality.xml. Trong khối <data>, hãy thêm một biến cho SleepQualityViewModel.
 <data>
       <variable
           name="sleepQualityViewModel"
           type="com.example.android.trackmysleepquality.sleepquality.SleepQualityViewModel" />
   </data>
  1. Đối với mỗi hình ảnh trong số 6 hình ảnh về chất lượng giấc ngủ, hãy thêm một trình xử lý lượt nhấp như trình xử lý bên dưới. Khớp mức chất lượng với hình ảnh.
android:onClick="@{() -> sleepQualityViewModel.onSetSleepQuality(5)}"
  1. Dọn dẹp và tạo lại dự án. Thao tác này sẽ giải quyết mọi lỗi với đối tượng liên kết. Nếu không, hãy xoá bộ nhớ đệm (File > Invalidate Caches / Restart (Tệp > Xoá bộ nhớ đệm/Khởi động lại)) rồi tạo lại ứng dụng.

Xin chúc mừng! Bạn vừa tạo một ứng dụng cơ sở dữ liệu Room hoàn chỉnh bằng cách sử dụng coroutine.

Giờ đây, ứng dụng của bạn hoạt động rất tốt. Người dùng có thể nhấn vào Bắt đầuDừng bao nhiêu lần tuỳ thích. Khi người dùng nhấn vào Dừng, họ có thể nhập chất lượng giấc ngủ. Khi người dùng nhấn vào Xoá, tất cả dữ liệu sẽ được xoá âm thầm ở chế độ nền. Tuy nhiên, tất cả các nút luôn được bật và có thể nhấp vào, điều này không làm hỏng ứng dụng nhưng cho phép người dùng tạo các đêm ngủ không đầy đủ.

Trong nhiệm vụ cuối cùng này, bạn sẽ tìm hiểu cách sử dụng bản đồ biến đổi để quản lý khả năng hiển thị của nút, nhờ đó người dùng chỉ có thể đưa ra lựa chọn phù hợp. Bạn có thể sử dụng một phương thức tương tự để hiển thị một thông báo thân thiện sau khi xoá tất cả dữ liệu.

Bước 1: Cập nhật trạng thái nút

Ý tưởng là đặt trạng thái nút sao cho ban đầu, chỉ có nút Start (Bắt đầu) được bật, tức là có thể nhấp vào nút này.

Sau khi người dùng nhấn vào Start (Bắt đầu), nút Stop (Dừng) sẽ được bật và nút Start sẽ không được bật. Nút Xoá chỉ được bật khi có dữ liệu trong cơ sở dữ liệu.

  1. Mở tệp bố cục fragment_sleep_tracker.xml.
  2. Thêm thuộc tính android:enabled vào mỗi nút. Thuộc tính android:enabled là một giá trị boolean cho biết nút có được bật hay không. (Bạn có thể nhấn vào nút đã bật; bạn không thể nhấn vào nút đã tắt.) Đặt giá trị của thuộc tính thành một biến trạng thái mà bạn sẽ xác định sau.

start_button:

android:enabled="@{sleepTrackerViewModel.startButtonVisible}"

stop_button:

android:enabled="@{sleepTrackerViewModel.stopButtonVisible}"

clear_button:

android:enabled="@{sleepTrackerViewModel.clearButtonVisible}"
  1. Mở SleepTrackerViewModel và tạo 3 biến tương ứng. Chỉ định cho mỗi biến một phép biến đổi để kiểm thử biến đó.
  • Nút Start (Bắt đầu) sẽ được bật khi tonightnull.
  • Nút Stop (Dừng) sẽ được bật khi tonight không phải là null.
  • Bạn chỉ nên bật nút Xoá nếu nights (và do đó là cơ sở dữ liệu) có chứa các đêm ngủ.
val startButtonVisible = Transformations.map(tonight) {
   it == null
}
val stopButtonVisible = Transformations.map(tonight) {
   it != null
}
val clearButtonVisible = Transformations.map(nights) {
   it?.isNotEmpty()
}
  1. Chạy ứng dụng và thử nghiệm các nút.

Bước 2: Sử dụng thanh thông báo nhanh để thông báo cho người dùng

Sau khi người dùng xoá cơ sở dữ liệu, hãy cho người dùng thấy thông báo xác nhận bằng tiện ích Snackbar. Thanh thông báo nhanh cung cấp thông tin phản hồi ngắn gọn về một thao tác thông qua một thông báo ở cuối màn hình. Snackbar sẽ biến mất sau một khoảng thời gian chờ, sau khi người dùng tương tác ở nơi khác trên màn hình hoặc sau khi người dùng vuốt snackbar ra khỏi màn hình.

Hiện thanh thông báo là một tác vụ giao diện người dùng và cần diễn ra trong mảnh. Quyết định hiển thị thanh thông báo nhanh trong ViewModel. Để thiết lập và kích hoạt một thanh thông báo khi dữ liệu bị xoá, bạn có thể sử dụng cùng một kỹ thuật như khi kích hoạt thao tác điều hướng.

  1. Trong SleepTrackerViewModel, hãy tạo sự kiện được đóng gói.
private var _showSnackbarEvent = MutableLiveData<Boolean>()

val showSnackBarEvent: LiveData<Boolean>
   get() = _showSnackbarEvent
  1. Sau đó, hãy triển khai doneShowingSnackbar().
fun doneShowingSnackbar() {
   _showSnackbarEvent.value = false
}
  1. Trong SleepTrackerFragment, trong onCreateView(), hãy thêm một đối tượng tiếp nhận dữ liệu:
sleepTrackerViewModel.showSnackBarEvent.observe(this, Observer { })
  1. Bên trong khối trình quan sát, hãy hiển thị thanh thông báo và đặt lại sự kiện ngay lập tức.
   if (it == true) { // Observed state is true.
       Snackbar.make(
               activity!!.findViewById(android.R.id.content),
               getString(R.string.cleared_message),
               Snackbar.LENGTH_SHORT // How long to display the message.
       ).show()
       sleepTrackerViewModel.doneShowingSnackbar()
   }
  1. Trong SleepTrackerViewModel, hãy kích hoạt sự kiện trong phương thức onClear(). Để thực hiện việc này, hãy đặt giá trị sự kiện thành true bên trong khối launch:
_showSnackbarEvent.value = true
  1. Tạo và chạy ứng dụng của bạn!

Dự án Android Studio: TrackMySleepQualityFinal

Việc triển khai tính năng theo dõi chất lượng giấc ngủ trong ứng dụng này giống như chơi một bản nhạc quen thuộc ở một khoá nhạc mới. Mặc dù các chi tiết có thay đổi, nhưng mẫu cơ bản của những việc bạn đã làm trong các lớp học lập trình trước đó trong bài học này vẫn giữ nguyên. Việc nhận biết những mẫu này giúp bạn lập trình nhanh hơn nhiều, vì bạn có thể sử dụng lại mã từ các ứng dụng hiện có. Sau đây là một số mẫu được sử dụng trong khoá học này cho đến nay:

  • Tạo ViewModelViewModelFactory, đồng thời thiết lập một nguồn dữ liệu.
  • Kích hoạt chế độ điều hướng. Để tách biệt các mối lo ngại, hãy đặt trình xử lý lượt nhấp trong mô hình thành phần hiển thị và thao tác điều hướng trong mảnh.
  • Sử dụng tính năng đóng gói với LiveData để theo dõi và phản hồi các thay đổi về trạng thái.
  • Sử dụng các phép biến đổi với LiveData.
  • Tạo một cơ sở dữ liệu singleton.
  • Thiết lập coroutine cho các thao tác với cơ sở dữ liệu.

Kích hoạt thao tác điều hướng

Bạn xác định các đường dẫn điều hướng có thể có giữa các mảnh trong một tệp điều hướng. Có một số cách khác nhau để kích hoạt thao tác điều hướng từ một mảnh này sang mảnh tiếp theo. bao gồm:

  • Xác định trình xử lý onClick để kích hoạt thao tác điều hướng đến một mảnh đích.
  • Ngoài ra, để bật thao tác điều hướng từ một mảnh sang mảnh tiếp theo, hãy làm như sau:
  • Xác định giá trị LiveData để ghi lại nếu thao tác điều hướng sẽ diễn ra.
  • Đính kèm một đối tượng tiếp nhận dữ liệu vào giá trị LiveData đó.
  • Sau đó, mã của bạn sẽ thay đổi giá trị đó bất cứ khi nào cần kích hoạt hoặc hoàn tất thao tác điều hướng.

Đặt thuộc tính android:enabled

  • Thuộc tính android:enabled được xác định trong TextView và được kế thừa bởi tất cả các lớp con, kể cả Button.
  • Thuộc tính android:enabled xác định liệu View có được bật hay không. Ý nghĩa của "đã bật" sẽ khác nhau tuỳ theo lớp con. Ví dụ: EditText không được bật sẽ ngăn người dùng chỉnh sửa văn bản có trong đó và Button không được bật sẽ ngăn người dùng nhấn vào nút.
  • Thuộc tính enabled không giống với thuộc tính visibility.
  • Bạn có thể sử dụng bảng chuyển đổi để đặt giá trị của thuộc tính enabled cho các nút dựa trên trạng thái của một đối tượng hoặc biến khác.

Các điểm khác được đề cập trong lớp học lập trình này:

  • Để kích hoạt thông báo cho người dùng, bạn có thể sử dụng cùng một kỹ thuật như khi kích hoạt thao tác điều hướng.
  • Bạn có thể dùng Snackbar để thông báo cho người dùng.

Khoá học của Udacity:

Tài liệu dành cho nhà phát triển Android:

Phần này liệt kê các bài tập về nhà cho học viên của lớp học lập trình này trong phạm vi khoá học có người hướng dẫn. Người hướng dẫn phải thực hiện các việc sau đây:

  • Giao bài tập về nhà nếu cần.
  • Trao đổi với học viên về cách nộp bài tập về nhà.
  • Chấm điểm bài tập về nhà.

Người hướng dẫn có thể sử dụng các đề xuất này ít hoặc nhiều tuỳ ý và nên giao cho học viên bất kỳ bài tập về nhà nào khác mà họ cảm thấy phù hợp.

Nếu bạn đang tự học các lớp học lập trình, hãy sử dụng những bài tập về nhà này để kiểm tra kiến thức của mình.

Trả lời các câu hỏi sau

Câu hỏi 1

Một cách để cho phép ứng dụng của bạn kích hoạt thao tác điều hướng từ một mảnh này sang mảnh khác là sử dụng giá trị LiveData để cho biết có kích hoạt thao tác điều hướng hay không.

Các bước để sử dụng giá trị LiveData (gọi là gotoBlueFragment) nhằm kích hoạt thao tác điều hướng từ mảnh màu đỏ đến mảnh màu xanh dương là gì? Hãy chọn tất cả các câu thích hợp:

  • Trong ViewModel, hãy xác định giá trị LiveData gotoBlueFragment.
  • Trong RedFragment, hãy quan sát giá trị gotoBlueFragment. Triển khai mã observe{} để chuyển đến BlueFragment khi thích hợp, sau đó đặt lại giá trị của gotoBlueFragment để cho biết quá trình điều hướng đã hoàn tất.
  • Đảm bảo mã của bạn đặt biến gotoBlueFragment thành giá trị kích hoạt thao tác điều hướng bất cứ khi nào ứng dụng cần chuyển từ RedFragment sang BlueFragment.
  • Đảm bảo mã của bạn xác định một trình xử lý onClick cho View mà người dùng nhấp vào để chuyển đến BlueFragment, trong đó trình xử lý onClick sẽ quan sát giá trị goToBlueFragment.

Câu hỏi 2

Bạn có thể thay đổi trạng thái bật (có thể nhấp) hoặc tắt của một Button bằng cách sử dụng LiveData. Làm cách nào để bạn đảm bảo rằng ứng dụng của mình thay đổi nút UpdateNumber sao cho:

  • Nút này sẽ được bật nếu myNumber có giá trị lớn hơn 5.
  • Nút này sẽ không được bật nếu myNumber bằng hoặc nhỏ hơn 5.

Giả sử bố cục chứa nút UpdateNumber bao gồm biến <data> cho NumbersViewModel như minh hoạ ở đây:

<data>
   <variable
       name="NumbersViewModel"
       type="com.example.android.numbersapp.NumbersViewModel" />
</data>

Giả sử mã nhận dạng của nút trong tệp bố cục là như sau:

android:id="@+id/update_number_button"

Bạn cần làm gì khác? Hãy chọn mọi câu trả lời phù hợp.

  • Trong lớp NumbersViewModel, hãy xác định một biến LiveDatamyNumber, đại diện cho số. Đồng thời, hãy xác định một biến có giá trị được đặt bằng cách gọi Transform.map() trên biến myNumber. Biến này sẽ trả về một giá trị boolean cho biết số đó có lớn hơn 5 hay không.

    Cụ thể, trong ViewModel, hãy thêm mã sau:
val myNumber: LiveData<Int>

val enableUpdateNumberButton = Transformations.map(myNumber) {
   myNumber > 5
}
  • Trong bố cục XML, hãy đặt thuộc tính android:enabled của update_number_button button thành NumberViewModel.enableUpdateNumbersButton.
android:enabled="@{NumbersViewModel.enableUpdateNumberButton}"
  • Trong Fragment sử dụng lớp NumbersViewModel, hãy thêm một trình quan sát vào thuộc tính enabled của nút.

    Cụ thể, trong Fragment, hãy thêm mã sau:
// Observer for the enabled attribute
viewModel.enabled.observe(this, Observer<Boolean> { isEnabled ->
   myNumber > 5
})
  • Trong tệp bố cục, hãy đặt thuộc tính android:enabled của update_number_button button thành "Observable".

Chuyển sang bài học tiếp theo: 7.1 Kiến thức cơ bản về RecyclerView

Để biết đường liên kết đến các lớp học lập trình khác trong khoá học này, hãy xem trang đích của lớp học lập trình Kiến thức cơ bản về cách tạo ứng dụng Android bằng Kotlin.