详解android如何设计一个全局可调用的viewmodel对象-kb88凯时官网登录

来自:网络
时间:2023-07-25
阅读:
免费资源网 - https://freexyz.cn/
目录

一、思路

viewmodel对象是存储在viewmodelstore中的,那么如果我们创建一个全局使用的viewmodelstore并且在获取viewmodel对象的时候从它里面获取就可以了。

viewmodel是通过viewmodelproviderget方法获取的,一般是viewmodelprovider(owner: viewmodelstoreowner, factory: factory).get(viewmodel::class.java)

如何将viewmodelproviderviewmodelstore关联起来? 纽带就是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)
        )
    }
    fun  getapplicationscopeviewmodel(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 fun  fragment.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)
        }
    }
}

baseactivitybasefragment中调用上述扩展方法

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对象的资料请关注其它相关文章!

免费资源网 - https://freexyz.cn/
返回顶部
顶部
网站地图