目录
一、思路
viewmodel
对象是存储在viewmodelstore
中的,那么如果我们创建一个全局使用的viewmodelstore
并且在获取viewmodel
对象的时候从它里面获取就可以了。
viewmodel
是通过viewmodelprovider
的get
方法获取的,一般是viewmodelprovider(owner: viewmodelstoreowner, factory: factory).get(viewmodel::class.java)
。
如何将viewmodelprovider
与viewmodelstore
关联起来? 纽带就是viewmodelstoreowner
, viewmodelstoreowner
是一个接口,需要实现getviewmodelstore()
方法,而该方法返回的就是viewmodelstore
:
public interface viewmodelstoreowner { /** * returns owned {@link viewmodelstore} * * @return a {@code viewmodelstore} */ @nonnull viewmodelstore getviewmodelstore(); //返回一个viewmodelstore }
让某个类实现这个接口,重写方法返回我们定义的viewmodelstore
就可以了。
至于上面viewmodelprovider
构造方法的第二个参数factory
是什么呢?
源码中提供了二种factory
,一种是newinstancefactory
,一种是androidviewmodelfactory
,它们的主要区别是:
newinstancefactory创建viewmodel时,会为每个activity或fragment创建一个新的viewmodel实例,这会导致viewmodel无法在应用程序的不同部分共享数据。(componentactivity源码getdefaultviewmodelproviderfactory方法)
androidviewmodelfactory可以访问应用程序的全局状态,并且viewmodel实例可以在整个应用程序中是共享的。
根据我们的需求,需要用的是androidviewmodelfactory。
二、具体实现
1、方式一:可以全局添加和获取任意viewmodel
定义application,ktx.kt
文件
import android.app.application lateinit var appcontext: application fun setapplicationcontext(context: application) { appcontext = context }
定义全局可用的viewmodelowner
实现类
object applicationscopeviewmodelprovider : viewmodelstoreowner { private val eventviewmodelstore: viewmodelstore = viewmodelstore() override fun getviewmodelstore(): viewmodelstore { return eventviewmodelstore } private val mapplicationprovider: viewmodelprovider by lazy { viewmodelprovider( applicationscopeviewmodelprovider, viewmodelprovider.androidviewmodelfactory.getinstance(appcontext) ) } fungetapplicationscopeviewmodel(modelclass: class ): t { return mapplicationprovider.get(modelclass) } }
定义一个viewmodel
通过stateflow
定义发送和订阅事件的方法
class eventviewmodel : viewmodel() { private val mutablestateflow = mutablestateflow(0) fun postevent(state: int) { mutablestateflow.value = state } fun observeevent(scope: coroutinescope? = null, method: (int) -> unit = { _ -> }) { val eventscope = scope ?: viewmodelscope eventscope.launch { mutablestateflow.collect { method.invoke(it) } } } }
定义一个调用的类
object flowevent { //发送事件 fun postevent(state: int) { applicationscopeviewmodelprovider.getapplicationscopeviewmodel(eventviewmodel::class.java) .postevent(state) } //订阅事件 fun observeevent(scope: coroutinescope? = null, method: (int) -> unit = { _ -> }) { applicationscopeviewmodelprovider.getapplicationscopeviewmodel(eventviewmodel::class.java) .observeevent(scope, method) } }
测试代码如下:
class mainactivity : appcompatactivity() { override fun oncreate(savedinstancestate: bundle?) { super.oncreate(savedinstancestate) setcontentview(r.layout.activity_main) //打印协程名称 system.setproperty("kotlinx.coroutines.debug", "on") flowevent.observeevent { printmsg("mainactivity observeevent before :$it") } //修改值 flowevent.postevent(1) flowevent.observeevent { printmsg("mainactivity observeevent after :$it") } } } //日志 内容:mainactivity observeevent before :0 线程:main @coroutine#1 内容:mainactivity observeevent before :1 线程:main @coroutine#1 内容:mainactivity observeevent after :1 线程:main @coroutine#2
2、方式二:更方便在activity和fragment中调用
定义application,让baseapplication
实现viewmodelstoreowner
//baseapplication实现viewmodelstoreowner接口 class baseapplication : application(), viewmodelstoreowner { private lateinit var mappviewmodelstore: viewmodelstore private var mfactory: viewmodelprovider.factory? = null override fun oncreate() { super.oncreate() //设置全局的上下文 setapplicationcontext(this) //创建viewmodelstore mappviewmodelstore = viewmodelstore() } override fun getviewmodelstore(): viewmodelstore = mappviewmodelstore /** * 获取一个全局的viewmodel */ fun getappviewmodelprovider(): viewmodelprovider { return viewmodelprovider(this, this.getappfactory()) } private fun getappfactory(): viewmodelprovider.factory { if (mfactory == null) { mfactory = viewmodelprovider.androidviewmodelfactory.getinstance(this) } return mfactory as viewmodelprovider.factory } }
ktx.kt
文件也有变化,如下
lateinit var appcontext: application fun setapplicationcontext(context: application) { appcontext = context } //定义扩展方法 inline funfragment.getappviewmodel(): vm { (this.requireactivity().application as? baseapplication).let { if (it == null) { throw nullpointerexception("application does not inherit from baseapplication") } else { return it.getappviewmodelprovider().get(vm::class.java) } } } //定义扩展方法 inline fun appcompatactivity.getappviewmodel(): vm { (this.application as? baseapplication).let { if (it == null) { throw nullpointerexception("application does not inherit from baseapplication") } else { return it.getappviewmodelprovider().get(vm::class.java) } } }
在baseactivity
和basefragment
中调用上述扩展方法
abstract class baseactivity: appcompatactivity() { //创建viewmodel对象 val eventviewmodel: eventviewmodel by lazy { getappviewmodel() } override fun oncreate(savedinstancestate: bundle?) { super.oncreate(savedinstancestate) } }
abstract class basefragment: fragment() { //创建viewmodel对象 val eventviewmodel: eventviewmodel by lazy { getappviewmodel() } override fun oncreate(savedinstancestate: bundle?) { super.oncreate(savedinstancestate) } }
测试代码
class mainactivity : baseactivity() { override fun oncreate(savedinstancestate: bundle?) { super.oncreate(savedinstancestate) setcontentview(r.layout.activity_main) //打印协程名称 system.setproperty("kotlinx.coroutines.debug", "on") eventviewmodel.observeevent { printmsg("mainactivity observeevent :$it") } findviewbyid(r.id.bt).setonclicklistener { //点击按钮修改值 eventviewmodel.postevent(1) //跳转到其他activity intent(this, twoactivity::class.java).also { startactivity(it) } } } }
class twoactivity : baseactivity() { override fun oncreate(savedinstancestate: bundle?) { super.oncreate(savedinstancestate) setcontentview(r.layout.activity_two) eventviewmodel.observeevent { printmsg("twoactivity observeevent :$it") } } }
日志
内容:mainactivity observeevent :0 线程:main @coroutine#1 内容:mainactivity observeevent :1 线程:main @coroutine#1 内容:twoactivity observeevent :1 线程:main @coroutine#2
以上就是详解android如何设计一个全局可调用的viewmodel对象的详细内容,更多关于android viewmodel对象的资料请关注其它相关文章!