欢迎来到代码驿站!

Android代码

当前位置:首页 > 移动开发 > Android代码

Kotlin类型安全构建器的一次运用记录

时间:2021-12-28 10:42:48|栏目:Android代码|点击:

在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)
  }
 }
}

总结

上一篇:viewpager实现自动循环轮播图

栏    目:Android代码

下一篇:将文件放到Android模拟器的SD卡中的两种解决方法

本文标题:Kotlin类型安全构建器的一次运用记录

本文地址:http://www.codeinn.net/misctech/188299.html

推荐教程

广告投放 | 联系我们 | 版权申明

重要申明:本站所有的文章、图片、评论等,均由网友发表或上传并维护或收集自网络,属个人行为,与本站立场无关。

如果侵犯了您的权利,请与我们联系,我们将在24小时内进行处理、任何非本站因素导致的法律后果,本站均不负任何责任。

联系QQ:914707363 | 邮箱:codeinn#126.com(#换成@)

Copyright © 2020 代码驿站 版权所有