Android Kotlin Fundamentals 06.3: Dùng LiveData để kiểm soát các trạng thái của nút

Lớp học lập trình này nằm trong khóa học về Khái niệm cơ bản về Android Kotlin. Bạn sẽ nhận được nhiều giá trị nhất từ khóa học này nếu bạn làm việc qua các lớp học lập trình theo trình tự. Tất cả các lớp học lập trình trong khóa học đều có trên trang đích của các lớp học lập trình cơ bản về Android Kotlin.

Giới thiệu

Lớp học lập trình này tóm tắt cách sử dụng ViewModel và các mảnh cùng nhau để triển khai hệ thống điều hướng. Hãy nhớ rằng mục tiêu là đặt logic when để điều hướng vào ViewModel, nhưng xác định đườ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 hãy sử dụng các mô hình chế độ xem, mảnh, LiveData và đối tượng tiếp nhận dữ liệu.

Lớp học lập trình kết luận bằng cách hiển thị một cách thông minh để theo dõi trạng thái của nút với mã tối thiểu, để mỗi nút được bật và có thể nhấp vào khi người dùng nhấn vào nút đó một cách hợp lý.

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

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

  • Xây dựng một giao diện người dùng (UI) cơ bản bằng cách sử dụng một hoạt động, mảnh và chế độ xem.
  • Di chuyển giữa các mảnh và sử dụng safeArgs để chuyển dữ liệu giữa các mảnh.
  • Xem các mô hình, xem thông tin về nhà máy, phép biến đổi, LiveData và các đối tượng tiếp nhận dữ liệu của các mô hình đó.
  • 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 đối tượng.
  • Cách sử dụng coroutine để 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 chất lượng giấc ngủ hiện có trong cơ sở dữ liệu.
  • Cách sử dụng LiveData để theo dõi trạng thái của các nút.
  • Cách hiển thị 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 TrackMySleepChất lượng để 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ả.
  • Hãy dùng LiveData để kích hoạt việc hiển thị 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 xây dựng bản ghi chất lượng giấc ngủ và giao diện người dùng hoàn thiện của ứng dụng TrackMySleepChất lượng.

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

Màn hình đầu tiên (hiển thị ở bên trái) có các nút để bắt đầu và dừng theo dõi. Màn hình hiển thị tất cả dữ liệu giấc ngủ của người dùng. Nút Xóa xóa 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 hiển thị ở bên phải, cho biết mức chọn điểm xếp hạng 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át triển, ứng dụng sẽ hiển thị cả biểu tượng khuôn mặt và giá trị tương đương bằng số.

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

  • Người dùng mở ứng dụng và hiển thị 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 Bắt đầu đã tắt và nút Dừng.
  • 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 sẽ đóng lại và màn hình theo dõi hiển thị thời gian ngủ và chất lượng giấc ngủ. Nút Dừng bị tắt và nút Bắt đầu đang bật. Ứng dụng đã sẵn sàng cho một đêm khác.
  • Nút Xóa được 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 Xóa, tất cả dữ liệu của họ sẽ bị xóa mà không cần truy cập lại – không có "Bạn có chắc chắn{5}quot; tin nhắn không.

Ứng dụng này dùng một cấu trúc đơn giản như trong bối cảnh của cấu trúc đầy đủ. Ứng dụng này 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 Phòng

Lớp học lập trình này giả định rằng bạn biết cách triển khai tính năng điều hướng bằng cách sử dụng các mảnh và tệp điều hướng. Để tiết kiệm công việc của bạn, chúng tôi cung cấp rất nhiều 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 cuối cùng hoặc tải mã dành cho người mới bắt đầu xuống.
  2. Trong mã dành cho người mới bắt đầu, hãy kiểm tra SleepQualityFragment. Lớp này tăng cường bố cục, tải ứng dụng và trả về binding.root.
  3. Mở navigation.xml trong trình chỉnh sửa thiết kế. Bạn sẽ 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 sleepNightKey.

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

Bước 2: Thêm thông tin chỉ đường để theo dõi chất lượng giấc ngủ

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

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

  1. Mở SleepTrackerViewModel. Bạn cần thêm đ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 xếp hạng chất lượng.
  2. Trong SleepTrackerViewModel, hãy tạo một LiveData để thay đổi thời điểm bạn muốn ứng dụng chuyển đến SleepQualityFragment. Hãy dùng tính năng đóng gói để chỉ hiển thị phiên bản LiveData có thể tải cho ViewModel.

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

val navigateToSleepQuality: LiveData<SleepNight>
   get() = _navigateToSleepQuality
  1. Thêm một hàm doneNavigating() để đặt lại biến kích hoạt việc di chuyển.
fun doneNavigating() {
   _navigateToSleepQuality.value = null
}
  1. Trong trình xử lý lượt nhấp của nút Dừng, onStopTracking(), hãy kích hoạt trình điều hướng đến SleepQualityFragment. Đặt biến _navigateToSleepQuality ở cuối hàm làm giá trị cuối cùng trong khối launch{}. Xin lưu ý rằng biến này được đặt thành night. Khi biến này có một giá trị, ứng dụng sẽ chuyển đến SleepQualityFragment, đi qua đêm.
_navigateToSleepQuality.value = oldNight
  1. SleepTrackerFragment cần phải quan sát _navigateToSleepQuality để ứng dụng biết thời điểm nên di chuyển. Trong SleepTrackerFragment, ở onCreateView(), hãy thêm một đối tượng tiếp nhận dữ liệu cho navigateToSleepQuality(). Xin lưu ý rằng nội dung nhập cho mục 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 người quan sát, hãy di chuyển và chuyển theo mã của đêm hiện tại, sau đó gọi doneNavigating(). Nếu mục 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 và chạy ứng dụng. Nhấn vào Bắt đầu, sau đó nhấn vào Dừng để chuyển đến màn hình SleepQualityFragment. Để quay lại, hãy sử dụng nút Quay lại hệ thống.

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

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

  1. Trong gói sleepquality, hãy tạo hoặc mở SleepqualityViewModel.kt.
  2. Tạo một lớp SleepQualityViewModel lấy sleepNightKey và cơ sở dữ liệu làm đối số. Cũng như đối với SleepTrackerViewModel, bạn cần chuyển database từ nhà máy. Bạn cũng cần chuyển trong sleepNightKey từ thanh đ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 và ghi đè onCleared().
private val viewModelJob = Job()
private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)

override fun onCleared() {
   super.onCleared()
   viewModelJob.cancel()
}
  1. Để quay lại 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() để áp dụng cho tất cả hình ảnh 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:
  • Chạy một coroutine trong uiScope và chuyển sang người đ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 bảng điều hướng.

Xin lưu ý rằng mẫu mã bên dưới thực hiện mọi công việc trong trình xử lý lượt nhấp, thay vì tính đến hoạt động của cơ sở dữ liệu trong các ngữ cảnh khác nhau.

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 họa bên dưới). Lớp này sử dụng phiên bản của cùng một mã nguyên mẫu mà bạn đã thấy trước đó. Hãy kiểm tra mã trước khi bạn tiếp tục.
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 mảnh chất lượng giấc ngủ

  1. Mở SleepQualityFragment.kt.
  2. Sau onCreateView(), sau khi có application, bạn cần lấy arguments đi kèm với thanh điều hướng. Các đối số này nằm trong SleepQualityFragmentArgs. Bạn cần phải trích xuất các gói đó từ gói.
val arguments = SleepQualityFragmentArgs.fromBundle(arguments!!)
  1. Tiếp theo, hãy tải dataSource.
val dataSource = SleepDatabase.getInstance(application).sleepDatabaseDao
  1. Tạo trạng thái ban đầu, chuyển vào dataSourcesleepNightKey.
val viewModelFactory = SleepQualityViewModelFactory(arguments.sleepNightKey, dataSource)
  1. Lấy tệp 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 bỏ qua đối tượng đó ngay bây giờ.)
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 6 hình ảnh chất lượng giấc ngủ, hãy thêm một trình xử lý lượt nhấp như hình ảnh dưới đây. Khớp thông tin xếp hạng chất lượng với hình ảnh.
android:onClick="@{() -> sleepQualityViewModel.onSetSleepQuality(5)}"
  1. Dọn dẹp và xây dựng lại dự án của bạn. Thao tác này sẽ khắc phục mọi lỗi xảy ra với đối tượng liên kết. Nếu không, hãy xóa bộ nhớ đệm (Tệp > Vô hiệu hóa bộ nhớ đệm/Khởi động lại) và tạo lại ứng dụng.

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

Ứng dụng của bạn đang hoạt động rất hiệu quả. Người dùng có thể nhấn vào Bắt đầuDừng bao nhiêu lần tùy thích. Khi nhấn vào Dừng, người dùng có thể nhập chất lượng giấc ngủ. Khi người dùng nhấn vào Xóa, tất cả dữ liệu sẽ bị xóa ngầm trong nền. Tuy nhiên, tất cả các nút luôn được bật và có thể nhấp vào, không làm hỏng ứng dụng nhưng sẽ cho phép người dùng tạo đêm ngủ không trọn vẹn.

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ý chế độ hiển thị của nút để người dùng chỉ có thể đưa ra lựa chọn phù hợp. Bạn có thể 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 tất cả dữ liệu đã bị xóa.

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

Ý tưởng là đặt trạng thái nút để ở đầu, chỉ nút Start (Bật) mới được bật, nghĩa là nút này có thể nhấp được.

Sau khi người dùng nhấn vào Bắt đầu, nút Dừng sẽ bật và Bắt đầu sẽ không bật. Nút Xóa chỉ 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; nút bị tắt không thể#39.) Đặt cho thuộc tính giá trị của biến trạng thái mà bạn sẽ xác định ngay lập tức.

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 một biến đổi sẽ kiểm tra biến đó.
  • Nút Bắt đầu sẽ được bật khi tonightnull.
  • Nút Dừng phải được bật khi tonight không phải là null.
  • Bạn chỉ nên bật nút Xóa nếu nights, do đó, 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 của bạn và thử nghiệm với 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 xóa cơ sở dữ liệu, hãy hiển thị cho người dùng một thông báo xác nhận bằng cách sử dụng tiện ích Snackbar. Thanh thông báo nhanh cung cấp phản hồi ngắn gọn về một thao tác thông qua thông báo ở cuối màn hình. Thanh thông báo nhanh sẽ biến mất sau khi hết thời gian chờ, sau khi người dùng tương tác ở một nơi khác trên màn hình, hoặc sau khi người dùng vuốt thanh địa chỉ khỏi màn hình.

Việc hiển thị thanh thông báo nhanh là một tác vụ giao diện người dùng và nó sẽ diễn ra trong mảnh. Việc quyết định hiển thị thanh thông báo nhanh sẽ xảy ra ở ViewModel. Để thiết lập và kích hoạt thanh thông báo nhanh khi dữ liệu bị xóa, bạn có thể sử dụng kỹ thuật tương tự như để kích hoạt thanh đ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, ở 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 đối tượng tiếp nhận dữ liệu, hiển thị thanh thông báo nhanh 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: TrackMySleepquality cuối

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ư việc phát một bản nhạc quen thuộc trong một chìa khóa mới. Mặc dù chi tiết thay đổi, mẫu cơ bản của những gì bạn đã thực hiện 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 được những mẫu này giúp việc 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ó. Dưới đây là một số mẫu được sử dụng trong khóa học này cho đến thời điểm này:

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

Kích hoạt hệ thống đ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 tệp điều hướng. Có một số cách để kích hoạt thao tác di chuyển từ một mảnh đến mảnh tiếp theo. Trong đó có:

  • Xác định trình xử lý onClick để kích hoạt thao tác di chuyển đến một mảnh đích.
  • Ngoài ra, để cho phép di chuyển từ một mảnh đến mảnh tiếp theo:
  • Xác định giá trị LiveData để ghi lại hoạt động điều hướng.
  • Đí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 việc di chuyển cần được kích hoạt hoặc hoàn tất.

Đặt thuộc tính android:bật

  • 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, bao gồm 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 "enable" khác nhau theo lớp con. Ví dụ: một EditText không bật sẽ ngăn người dùng chỉnh sửa văn bản chứa trong đó, còn Button không bật sẽ ngăn người dùng nhấn vào nút.
  • Thuộc tính enabled không giống thuộc tính visibility.
  • Bạn có thể dùng bản đồ biến đổi để đặt giá trị cho thuộc tính enabled của 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 chính kỹ thuật mà bạn sử dụng để kích hoạt thao tác.
  • Bạn có thể sử dụng Snackbar để thông báo cho người dùng.

Khóa học từ 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à có thể được giao cho học viên đang làm việc qua lớp học lập trình này trong khóa học do người hướng dẫn tổ chức. Người hướng dẫn có thể làm những việc sau:

  • Giao bài tập về nhà nếu được yêu cầu.
  • Trao đổi với học viên 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 những đề xuất này ít hay nhiều tùy ý. Do đó, họ có thể thoải mái giao 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ự mình làm việc qua lớp học lập trình này, hãy thoải mái sử dụng các bài tập về nhà này để kiểm tra kiến thức của bạn.

Trả lời những câu hỏi này

Câu hỏi 1

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

Các bước để sử dụng giá trị LiveData, được gọi là gotoBlueFragment, để kích hoạt thao tác di chuyển 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 phù 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 là bạn đã hoàn tất việc di chuyển.
  • Hãy đảm bảo mã của bạn đặt biến gotoBlueFragment thành giá trị kích hoạt việc di chuyển bất cứ khi nào ứng dụng cần chuyển từ RedFragment đến BlueFragment.
  • Đảm bảo mã của bạn xác định trình xử lý onClick cho View mà người dùng nhấp để chuyển đến BlueFragment, trong đó trình xử lý onClick quan sát giá trị goToBlueFragment.

Câu hỏi 2

Bạn có thể thay đổi tùy chọn Button có được bật (có thể nhấp vào) hay không bằng cách sử dụng LiveData. Làm cách nào để đảm bảo rằng ứng dụng của bạn thay đổi nút UpdateNumber để:

  • 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ư được hiển thị dưới đây:

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

Giả sử mã của nút trong tệp bố cục 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 phù hợp.

  • Trong lớp NumbersViewModel, hãy xác định một biến LiveData, myNumber, đại diện cho số này. Ngoài ra, 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 đối tượng tiếp nhận dữ liệu 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 Khái niệm 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 khóa học này, hãy xem trang đích của các lớp học lập trình cơ bản về Android Kotlin.