###### tags: `Android` # MVVM 架構 在學習 MVVM 之前,可以先觀看 [Android 三種開發架構,MVC、MVP、MVVM怎麼選?](https://www.youtube.com/watch?v=nViX8m7gS7I) 來認識除了 MVVM 之外還有哪些架構,以及為什麼我們應該選擇使用 MVVM 架構。 Model:管理資料來源,如 Web API、本地資料庫 View:顯示 UI 和接收使用者動作 ViewModel:接收 View 的指令,並從 Model 取得 View 所需的資料 ## 建立基本的 MVVM 建立 Model:==DataModel== ```kotlin= class DataModel { interface onDataReadyCallback { fun onDataReady(data: String) } //模擬資料獲取時的延遲 fun retrieveData(callback: onDataReadyCallback) { Handler().postDelayed({ callback.onDataReady("New Data") }, 1000) } } ``` 建立 ViewModel:==MainViewModel== ```kotlin= class MainViewModel { private val dataModel = DataModel() fun refresh() { dataModel.retrieveData(object : DataModel.onDataReadyCallback { override fun onDataReady(data: String) { //TODO("Use observable to update UI") } }) } } ``` 建立 View:==MainActivity、activty_main== ```kotlin= class MainActivity : AppCompatActivity() { private lateinit var viewModel: MainViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) viewModel = MainViewModel() btn_refresh.setOnClickListener { viewModel.refresh() } } } ``` ```xml= <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/btn_refresh" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Refresh" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent"/> <ProgressBar android:id="@+id/progressBar" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> ``` 這樣就完成基本的 MVVM 架構,剩下的就是 View 如何接收資料並更新 UI 而這個部分會使用 Data Binding 來完成 View 與 ViewModel 的溝通。 ==為什麼要使用 Data Binding?== MVVM 是使用觀察者的方式達成,以前有人會自己寫觀察者模式來處理 但有了 ObservableField 後就省事很多,而在 Android 發展出 Data Binding 後 也將原本的 ObservableField 納入 Data Binding 函式庫中。 ## Jetpack Data Binding Data Binding 可以看[此篇教學](https://hackmd.io/USJfeNs2R1qLGp6rkEJQiw) ## Jetpack ViewModel 完成 DataBinding 後,目前的架構還需要處理生命週期問題,如螢幕旋轉後資料遺失,而 Jetpack 的 ViewModel 能解決這問題,它有 lifecycle-aware 的特性,不會因 Activity 被重建而清除,在每次重建都能持有相同實體。 ViewModel 可以看[此篇教學](https://hackmd.io/ROW4JBjqRTOrwLDltAeZDQ) ## Jetpack LiveData 由於 Data Binding 沒有 Lifecycle-aware 的特性,因此 View 在背景時仍會觸發更新,而 Jetpack 的 LiveData 能解決這問題,它有 lifecycle-aware 的特性,能確保 Activity、Fragment 只在活耀的狀態才會收到資料的變化。 LiveData 可以看[此篇教學](https://hackmd.io/Peh0693lSQSjpvBzjaMcIg?view)