前言
话说我真是怠惰啊,各种鸽,写jetpack又写设计模式还写个view,各种挖坑,算了,继续慢慢填,这次来聊下ViewModel
ViewModel
在Jetpcak里面,LifeCycles、ViewModel、LiveData这三个是相辅相成的,我个人的理解是ViewModel实现了LifeCycles的功能,也是有生命周期的感知的,而且它的生命周期更广(比Activity还要广)
也正因为如此,所以它也解决了2个问题:
1.当Activity/Fragment被销毁重建时,成员变量被清空(需要用onSaveInstanceState()保存数据恢复什么的)
2.当Activity/Fragment进行异步操作时导致的内存泄漏(虽然没有直接解决,而是提供了onCleared()这个方法让我们去处理)
FBI WARNING
正是因为ViewModel比Activity的生命周期还要长,所以ViewModel如果持有Activity的实例,那肯定要产生内存泄漏的(如果业务需要,使用AndroidViewModel(application))
导入
首先我们要依赖Google仓库,在project -> build.gradle里
repositories {
//一般来说自动生成的项目都会默认依赖Google和Jcenter仓库的
google()
jcenter()
}
然后是Module -> build.gradle
dependencies {
def lifecycle_version = "2.0.0"
// ViewModel and LiveData
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
// alternatively - just ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version" // For Kotlin use lifecycle-viewmodel-ktx
// alternatively - just LiveData
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
// alternatively - Lifecycles only (no ViewModel or LiveData). Some UI
// AndroidX libraries use this lightweight import for Lifecycle
implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version" // For Kotlin use kapt instead of annotationProcessor
// alternately - if using Java8, use the following instead of lifecycle-compiler
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
// optional - ReactiveStreams support for LiveData
implementation "androidx.lifecycle:lifecycle-reactivestreams:$lifecycle_version" // For Kotlin use lifecycle-reactivestreams-ktx
// optional - Test helpers for LiveData
testImplementation "androidx.arch.core:core-testing:$lifecycle_version"
}
看注释按需导入
使用
简单到爆炸的用法...
class MyViewModel : ViewModel(){
var name: String = "xiao"
}
在Activity里面调用
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val model = ViewModelProviders.of(this)[MyViewMode::class.java]
tv.text = model.name
}
}
可能会遇到的问题, ViewModelProviders.of(this)爆红,这个一般是AndroidX的包引起的,将项目迁移至AndroidX就好了,Refactor -> Migrate to AndroidX
Fragment共享
这个也是ViewModel解决的痛点之一,of方法里面不仅可以传Activity对象,也可以传Fragment对象,所以在同Activity下的不同Fragment,我们可以传入相同的Activity对象来获得实例,以此解决Fragment之间的通讯问题。比起直接弄个全局静态对象来通信算是好太多了
//FirstFragment
class FirstFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_first, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val mode = activity?.let { ViewModelProviders.of(it).get(MyViewMode::class.java) }
text.text = mode.toString()
}
}
//SecondFragment
class SecondFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_second, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val mode = activity?.let { ViewModelProviders.of(it).get(MyViewMode::class.java) }
text.text = mode.toString()
}
}
可以看到2个Fragment拿到的是同一个对象
总结
ViewModel其实挺简单的,在我的理解就是一个全局的静态对象,然后又有了生命周期,但其实它带来的是一种新的思想,MVVM,也就是数据驱动,viewModel作为中枢,从数据库获取数据,然后交由liveData通知UI更新,关于liveData,我们下期见
网友评论