iT邦幫忙

2025 iThome 鐵人賽

DAY 16
0
Mobile Development

現代Android jetpack compose開發入門系列 第 16

Day 16:甚麼是ViewModel,如何分離UI與邏輯資料

  • 分享至 

  • xImage
  •  

上篇提到了無法在TodoDisplay展示正確的任務,因為目前的程式都是寫死的,現在要讓資料流通,才真的能作為一個應用使用

MVVM架構

說到Android力推的MVVM架構,他其實是一種將整個專案變得更加有條理的架構
他是將UI層(view)、數據層(model)、邏輯層(viewmodel)分開處理:

  • Model:資料來源(Room、網路、Repository 等)
  • View:單純顯示,不處理資料邏輯(Compose 的 Composable UI)
  • ViewModel:中介層,接收 UI 輸入,處理資料,最後把結果再送回 UI

簡單說說他的好壞:
Pros

  • 可以集中的存資料
  • 集中的處理大部分邏輯
  • 獨立UI顯示部分
  • 每個層都可分類分項更清晰
  • 可以單獨測試
    Cons
  • 幾乎無法跨域溝通(viewmodel)
  • 初始化複雜

我自己是覺得在良好的規劃下,MVVM架構明顯比單純的宣告remember state更有擴展力也更好檢查,所以在多數情況下我推薦使用MVVM
但如果只是 demo 小專案,用 remember { mutableStateOf() } 也沒關係,但只要專案稍微大一點,MVVM 就是必要的

ViewModel

這就是上文所說的邏輯層,他負責處理數據,並向UI層傳遞數據讓它顯示
目前我們已經說過了UI層,也就是最基本的UI顯示部分,至於數據層,會在大概Day 21時使用與結合
由於viewmodel部分比較複雜,這邊先介紹最基本的宣告與使用
先在MainActivity旁邊建立一個新的檔案

建立

data class TodoItem(var title: String, var content: String, var group: String, var done: Boolean = false)  
  
class GlobalVM : ViewModel() {  
    private val _todoList = MutableStateFlow<List<TodoItem>>(emptyList())  
    val todoList: StateFlow<List<TodoItem>> = _todoList  
  
    fun addTodo(todoItem: TodoItem) {  
        _todoList.update { current ->
            current + todoItem 
        }
	}  
}

大致講解viewmodel的宣告與操作

  • 所有的viewmodel都是從ViewModel()繼承的class
  • viewmodel中的資料以StateFlow形式存在
  • 通常會有一個private和一個public來管理一組數據,在例子中是todoList
    • MutableStateFlow可以更改數據,所以要避免再UI層操作,因此是private
    • StateFlow是唯獨的數據流,因此是給UI層使用的
  • 所有的修改數據邏輯都要以函數寫在viewmodel中
  • 修改數據必須使用.update方式,不可以直接覆寫
  • 通常數據會用data class存成一個大的數據

使用

fun Example(globalVM: GlobalVM = viewModel()) {
	val globalState by globalVM.todoList.collectAsState()
}

透過viewModel()可以直接在元件建立的時候產生一個新的viewmodel
接著就可以使用collectAsState將viewmodel中的數據取出使用

如果同時有太多元件collectState,可能會影響效能


上一篇
Day 15:將導覽套用在應用上
下一篇
Day 17:架構適用於App的ViewModel
系列文
現代Android jetpack compose開發入門22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言