1. 程式人生 > 程式設計 >Kotlin型別安全構建器的一次運用記錄

Kotlin型別安全構建器的一次運用記錄

在android官方指導的相關應用框架中,用到一個Resource類來表示網路請求的狀態與結果

// A generic class that contains data and status about loading this data.
sealed class Resource<T>(
 val data: T? = null,val message: String? = null
) {
 class Success<T>(data: T) : Resource<T>(data)
 class Loading<T>(data: T? = null) : Resource<T>(data)
 class Error<T>(message: String,data: T? = null) : Resource<T>(data,message)
}

大多數情況下我們在activity裡面是這樣用的

private val testViewModel : TestViewModel by viewModels()

private fun getUserInfo(uid: String) {
 testViewModel.userInfoData.observe(this,Observer {
  when (it.status) {
   Status.SUCCESS -> TODO()
   Status.ERROR -> TODO()
   Status.LOADING -> TODO()
  }
 })
 testViewModel.setUserId(uid)
}

這樣寫多了感覺好煩,每次都是when(),有沒有更爽的寫法呢?比如這樣?

private fun getUserInfo(uid: String) {
 testViewModel.userInfoData.observe(this,Observer {
  success {
   
  }
  error {
   
  }
  loading {
   
  }
 })
 testViewModel.setUserId(uid)
}

當我只需要處理success的時候,我可以不寫error/loading情況。

kotlin的型別安全構建器可以做到,我們先看下官方的示例

class HTML {
 fun body() { …… }
}

fun html(init: HTML.() -> Unit): HTML {
 val html = HTML() // 建立接收者物件
 html.init()  // 將該接收者物件傳給該 lambda
 return html
}

html {  // 帶接收者的 lambda 由此開始
 body() // 呼叫該接收者物件的一個方法
}

先分析下,我們需要的是一個實現了Observer介面的物件。

所以我們先定義一個類來實現Observer介面

class ResourceObserver<T: Any> : Observer<Resource<T>> {
 override fun onChanged(t: Resource<T>) {
  when(t) {
   is Resource.Success -> TODO()
   is Resource.Error -> TODO()
   is Resource.Loading -> TODO()
  }
 }
}

實現一個頂層函式,返回一個ResourceObserver物件

fun <T: Any> resourceObserver(init: ResourceObserver<T>.() -> Unit): ResourceObserver<T> {
 val observer = ResourceObserver<T>()
 observer.init()
 return observer 
}

呼叫該函式即可得到ResourceObserver物件

resourceObserver {
 //在此處可以呼叫物件內的成員函式
}

所以我的實現是

class ResourceObserver<T: Any> : Observer<Resource<T>> {
 private var success: (Resource.Success<T>.() -> Unit)? = null
 private var error: (Resource.Error.() -> Unit)? = null
 private var loading: (Resource.Loading<T>.() -> Unit)? = null
 
 fun success(s: (Resource.Success<T>.() -> Unit)) {
  success = s
 }
 
 fun error(e: Resource.Error.() -> Unit) {
  error = e
 }
 
 fun loading(l: Resource.Loading<T>.() -> Unit) {
  loading = l
 }
 
 override fun onChanged(t: Resource<T>) {
  when(t) {
   is Resource.Success -> success?.invoke(t)
   is Resource.Error -> error?.invoke(t)
   is Resource.Loading -> loading?.invoke(t)
  }
 }
}

總結

到此這篇關於Kotlin型別安全構建器的一次運用記錄的文章就介紹到這了,更多相關Kotlin型別安全構建器運用內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!