Chatbox

Các bạn vui lòng dùng từ ngữ lịch sự và có văn hóa,sử dụng Tiếng Việt có dấu chuẩn. Chúc các bạn vui vẻ!
19/05/2021 17:05 # 1
buiducduong
Cấp độ: 22 - Kỹ năng: 1

Kinh nghiệm: 17/220 (8%)
Kĩ năng: 0/10 (0%)
Ngày gia nhập: 25/09/2020
Bài gởi: 2327
Được cảm ơn: 0
Tìm hiểu MVVM pattern dành cho Android năm 2021


Tôi gần như chắc chắn 100% rằng bạn đã nghe thấy các từ “MVC”, “MVP”, “MVVM”, “MVI” , Mv bất cứ thứ gì 🤷 khi bạn tìm kiếm tài nguyên phát triển. Để hiểu MVVM, chúng ta cần đi đến những điều cơ bản. (Đừng lo lắng tôi sẽ đi thẳng vào vấn đề).

VẤN ĐỀ LÀ GÌ?

Khi chúng ta bắt đầu với việc phát triển android, chúng ta có xu hướng đặt tất cả logic của mình vào bên trong Activity, Fragment, View, v.v. Vì vậy, cuối cùng, “views” chúng ta có xu hướng làm nhiều việc hơn là chỉ hiển thị giao diện người dùng. Giờ đây, họ có thể lưu dữ liệu vào SharedPreferences, Databases hoặc thậm chí thực hiện các cuộc gọi mạng và xử lý tất cả các tác vụ bổ sung này ở một nơi.

SOFTWARE DESIGN PATTERNS

Một SOFTWARE DESIGN PATTERNS nói chung là một giải pháp tái sử dụng cho một vấn đề thường xảy ra trong một bối cảnh cụ trong thiết kế phần mềm.

Nếu bạn muốn, bạn có thể đi sâu vào nó, có rất nhiều tài nguyên về nó. Được rồi, chúng ta xác định được vấn đề và chúng ta biết mình có các công cụ để khắc phục sự cố.

MVVM

Chữ V là viết tắt của View có thể là Activity, Fragment hoặc thậm chí là tổng hợp ngay bây giờ. ViewModel là viết tắt của jetpack ViewModel của chúng tôi, là một lớp có thể tồn tại các thay đổi cấu hình. Được rồi, hãy đóng gói tất cả lại với nhau, View của chúng ta đăng ký các bản có thể quan sát được của ViewModel và phản ứng với bất kỳ thay đổi nào về Model . Cuối cùng! đây là chữ M của chúng ta, chữ M là viết tắt của Model Chờ đã, "Model " của bạn là ai hoặc là gì? Phần lớn các nguồn ngoài kia nói với bạn rằng Model của bạn là “nơi” bạn lấy dữ liệu, là nơi lưu trữ của bạn, v.v. Tôi nghĩ điều này là sai, và tôi sẽ cho bạn biết tại sao. Đây là phần trích dẫn của blog này từ Iveta Jurčíková Khái niệm Mô hình không có gì mới. Nó được Trygve Reenskaug định nghĩa lần đầu tiên vào năm 1979 như một phần của kiến trúc MVC. “Model chịu trách nhiệm đại diện cho trạng thái, cấu trúc và hành vi của mô hình tinh thần của người dùng.” “View trình bày thông tin mà nó truy xuất từ một hoặc nhiều đối tượng Model.” “Hãy để View đăng ký với Model như là một phần phụ thuộc của Model và để cho Model gửi các thông điệp thích hợp đến những người phụ thuộc của nó bất cứ khi nào nó thay đổi. “ Chúng ta đã kết thúc với một cái gì đó như thế này:

Model của chúng ta phải đại diện cho trạng thái hiện tại của View, có thể là trạng thái đang tải, thành công hoặc thất bại. Và View của chúng ta phải kết xuất giao diện người dùng theo trạng thái hiện tại.

SHOW ME THE CODE

Giả sử chúng ta phải hiển thị danh sách các bộ phim trong ứng dụng của mình. Chúng ta có thể biểu diễn trạng thái như lớp sau:

/**
 * Represents the state to render the UI in MovieListFragment.
 *
 * @param isLoading if true we have to show a progress bar, else hide the progress bar.
 * @param movies this list will be submited into recyclerview adapter.
 * @param error OneTimeEvent that wraps a failure object for display a Toast, Snackbar, etc only once.
 */
data class MovieListUiState(
    val isLoading: Boolean = false,
    val movies: List<MovieUi> = emptyList(),
    val error: OneTimeEvent<Failure>? = null
)

OneTimeEvent là gì ? Nó chỉ là một lớp tiện ích giúp chúng ta tiêu thụ các đối tượng chỉ một lần, để tránh hiển thị các quầy ăn nhanh, bánh mì nướng hai lần khi người dùng quay lại màn hình của bạn. Failure là gì? Là một lớp Sealed đại diện cho bất kỳ kiểu failure nào. Bạn có thể sử dụng ngoại lệ, chuỗi, v.v. Bất kỳ thứ gì phục vụ cho dự án của bạn để thông báo cho người dùng rằng đã xảy ra sự cố.

class MovieListFragment : Fragment(R.layout.fragment_movie_list) {

    ...

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initView()
        collectUiState()
    }

    private fun initView() {
        binding.rvMovies.adapter = MovieListAdapter()
    }

    private fun collectUiState() {
        viewLifecycleOwner.lifecycleScope.launch {
            moviesViewModel.uiState.collect { state ->
                renderUiState(state)
            }
        }
    }

    private fun renderUiState(state: MovieListUiState) {
        with(state) {
            // Progress
            binding.progressBarMovies.isVisible = isLoading

            // Bind movies.
            (binding.rvMovies.adapter as MovieListAdapter)
                .submitList(movies)

            // Empty view
            binding.tvMoviesEmpty.isVisible = !isLoading && movies.isEmpty()

            // Display error if any. Only once.
            error?.let {
                it.consumeOnce { failure ->
                    Toast.makeText(
                        requireContext(),
                        "$failure",
                        Toast.LENGTH_LONG
                    ).show()
                }
            }
        }
    }
  
  ...
}

Hãy để tôi giải thích 3 phương pháp đó.

  • initView () chỉ khởi tạo bộ chuyển đổi chế độ xem lại.
  • collectUiState () thu thập Luồng uiState. Bạn có thể sử dụng LiveData, điều đó không thành vấn đề.
  • renderUiState (trạng thái: MovieListUiState) đây là cái phụ trách RENDER UI theo trạng thái hiện tại.

Này Chris, còn ViewModel của tôi thì sao? ViewModel của bạn phải là cái chuẩn bị dữ liệu (có thể đến từ giao diện kho lưu trữ, ca sử dụng, v.v.) và sử dụng kết quả của nó để sửa đổi Trạng thái của bạn. Và đó là nó. Bây giờ bạn biết ai thực sự là Model của bạn trong thế giới MVVM của bạn.




 
Copyright© Đại học Duy Tân 2010 - 2024