iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 10
1
Mobile Development

從0開始,全方面自動化測試Android App系列 第 10

[Day 10] MVVM與單元測試

MVVM (Model-View-ViewModel)

MVVM是近年在Android開發中比較熱門的設計模式,這是因為google在2017年推出Architechture Component把MVVM的設計模式包裝在SDK裡也使得這一兩年在Android平台開發的使用率大幅上升,我們先來看一段MVVM的實作介紹,如果你對MVVM己經很熟想直接看結論可以直接跳到最後一段。

class MvvmActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_mvvm)

        val model = ViewModelProviders.of(this)[MyViewModel::class.java]
        model.apiManager = ServerApi()
        model.getUsers().observe(this, Observer<List<User>>{ users ->
            // update UI
        })
    }
}

class ServerApi {
    fun requestUser(): List<User>? {
        //implement remote connection
        return null
    }
}

class MyViewModel : ViewModel() {
    var apiManager: ServerApi? = null

    private val users: MutableLiveData<List<User>> by lazy {
        MutableLiveData<List<User>>().also {
            val list = loadUsers()?.filter { it.firstName == "Daniel" }
            it.postValue(list)
        }
    }

    fun getUsers(): LiveData<List<User>> {
        return users
    }

    private fun loadUsers(): List<User>? {
        return apiManager?.requestUser()
    }

}

上面程式碼範例,假設我們有一個MvvmActivity,MvvmActivity在onCreate()的時候就要跟Server要求User資料來顯示,所以我們有一個ServerApi的class在處理reqeust流程,然後在ServerApi裡面有個requestUser()的function會回傳User清單。然後我們創建一個MyViewModel的class去處理跟Server request後的資料。ViewModel要實作Android SDK提供的ViewModel介面之後我們就可以在Activity裡面利用ViewModelProvider來把我們自定的MyViewModel實體化出來使用,這時候我們就可以監聽ViewModel裡的Observer變數。而範例裡要被Activity觀察的變數是users,一但users有改變就通知Activity來做後續update UI的行為。

那users怎麼寫成觀察者模式的變數?這點Android SDK已經幫我們做完了,你也可以選擇自己做但是我不建議,我們只需要把users變數宣告成SDK內建的LiveData類別就可以使用ViewModel的觀察者模式了。而LiveData不僅僅只是實作observer而已,它還有強大的Android lifecycle aware的作用,可以防止Android常見的Activity memory leak。

範例中users這個LiveData會從private function loadUsers()去跟Server 去詢問資料再由reqeustUsers()中得到的資料,這裡用Kotlin的filter function去選擇firstName叫Daniel的user,最後用LiveData postValue的方法通知Activity的觀察者ViewModel已經改變,請同時update UI。

MVVM的好處

記得我在MVP的章節有講過在Presenter裡面我們會用constructor或是setter的方式注入view interface來呼叫抽象的function,好讓presenter跟activity溝通。雖然我們控制的是View的interface但帶入的其實是Activity的實體,而在Application實作當中我們常常會把非同步的task邏輯如server api reqeust,database或image processing等等放在presenter裡面來使用,當user在callback還沒回來前就先destroy Activity了(可能是主動back或被系統回收等等狀況),就會造成presenter所參照的reference消失了而導致applicaton crash。MVVM模式的出現剛好可以解決這個問題。

MVVM跟MPV不一樣的地方是MVVM用觀察者模式(Observer pattern)來替代Activity UI實體的抽象化,也就是原本在Presenter內被參考的Activity實體被換成ViewModel裡的觀察者物件,再從Activity內去listen這個觀察者物件的行為。利用這個方式我們就不用把Activity的reference放到Presenter裡去呼叫,也就是View跟ViewModel之間的關係被解耦。在MVP模式裡Presenter跟View並沒有解耦,對做單元測試上的好處相同的是它們把邏輯分開在另一個地方(Presenter & ViewModel)可以方便我們做單元測試。

關於MVVM測試程式的部份會在下一章節說明。


上一篇
[Day 9] 關於mockk的其它用法
下一篇
[Day 11]MVVM的單元測試
系列文
從0開始,全方面自動化測試Android App30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言