在去年的Google大会中,Google官方推出了新的开发组件:Lifecycle和LiveData。Lifecycle是监听数据生命周期变化的,这里不再赘述。我们来主要说说LiveData的应用,LiveData默认实现了LifecycleObserver接口,因此它是一个生命周期感知组件。观察者可以指定某一个Lifecycle给LiveData,并对数据进行监听。在Lifecycle稳定之后,Activity和Fragment都默认是LifecycleOwner,因此可以直接添加观察者。应用LiveData可以进行MVVM模式的开发,实现数据类似VUE中的双向绑定,这其实是很不错的。好了,话不多说,直接上代码吧。
这里我们先建立一个Project实体类(Model):
class Project {
var boid: String? = null
var type: String? = null
var title: String? = null
}
接下来就是ViewModel的编写了:
class ProjectViewModel<T> : ViewModel(){
private var url = ""
var project: LiveData<T>? = null
fun init(url: String) {
this.url = url
}
}
在这里我们使用了泛型,这是为实现通用的ViewModel做准备。毕竟在工程中,重复的代码我们是不想写很多的遍的吧。
好了,到这里ViewModel就已经建立起来了,现在我们在Activity中来进行应用监听。
val url = "你的接口地址"
viewModel = ViewModelProviders.of(this).get(ProjectViewModel<Project>()::class.java)
viewModel!!.init(url)
viewModel!!.project!!.observe(this, Observer<Project> {
//这里来刷新UI
})
ViewModel.project.observe看这句的代码的源码,你会发现这其实就是在添加观察者:
owner.getLifecycle().addObserver(wrapper);
上面我们提到了Activity和Fragment在Liftcycle稳定之后会默认是LiftcycleOwner这里得到了很好的体现。那么,现在万事俱备,只欠东风了。数据从哪里来呢?这个时候就需要一个专门来处理数据的类了。当然,你也可以把处理数据的模块直接放在ViewModel中进行,但是我不推荐你那样做。毕竟我们写代码还是要有逼格的对吗,能分的细致一点就分的细致一点,这样写出来的代码才优雅。
好了,现在我们来建立一个ProjectRepository类来处理数据:
class ProjectRepository<T> {
public fun<T> getProject(url:String):LiveData<T>{
val item = Project()
val data = MutableLiveData<T>()
doAsync {
val jsonStr = URL(url).readText()
try {
//TODO 这里来处理从接口获取的数据
uiThread {
//liveData实现了类似VUE中的数据双向绑定的概念,每次data中的value发生改变都会触发观察者向UI线程发送消息来刷新UI
data.value = item as T
item.title = "德玛西亚"
data.value = item
}
}catch (e:Exception){
e.printStackTrace()
}
}
return data
}
}
可以看到这里我们是从后台服务上获取的数据,并且运用的是anko中的方法。你也可以用你自己喜欢的方式来和服务器进行交互(okhttp,Retrofit等)。这样将数据获取分开来写还有一个好处就是当数据获取方式发生改变的时候可以直接改变获取方式就好了,简介明了,避免出现GOD CLASS。在代码的末尾处我们又人为的改变了title值,这是用来验证数据变化监听的。现在数据来源也有了,我们要把ProjectRepository和ProjectViewModel连接起来了:
class ProjectViewModel<T> : ViewModel() {
private var url = ""
var project: LiveData<T>? = null
val Repo = ProjectRepository<T>()
fun init(url: String) {
this.url = url
project = Repo.getProject(url)
}
}
这里init就是提供一个类似钥匙的作用。如果你的数据不是从服务器获取而是从本地数据库获取。那么这里的init的参数就有可能是一个查询的条件值了。好了到这里为止,一个简单的LiveData运用就写完了。