ViewModel中传入Context的方法

这篇博客介绍了如何在Android开发中绕过ViewModel官方不建议添加Context的限制,提供了两种解决方案:1) 使用Kotlin扩展函数在获取ViewModel时传入Context;2) 创建自定义的ViewModelProvider.Factory来实例化时注入Context。示例代码详细展示了这两种方法的实现和使用方式,适用于需要在ViewModel中使用Context的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ViewModel使用的越来越多了,严格来说,官方并不建议你在ViewModel中添加Context的引用。同时,ViewModel的构造方法是没有任何参数的,有的时候会很不灵活。以下记录两种方法。

#1.通过kotlin的拓展函数


fun <T : ViewModelProvider, V : ViewModel> T.get(
    key: String,
    modelClass: Class<V>,
    context: FragmentActivity
): V {
    val model = get(key, modelClass)
    if (model is TestViewModel) {
        model.addContext(context)
    }
    return model
}

fun <T : ViewModelProvider, V : ViewModel> T.get(
    key: String,
    modelClass: Class<V>,
    context: Context
): V {
    val model = get(key, modelClass)
    if (model is TestViewModel) {
        model.addContext(context)
    }
    return model
}

fun <T : ViewModelProvider, V : ViewModel> T.get(
    modelClass: Class<V>,
    context: FragmentActivity
): V {
    val model = get(modelClass)
    if (model is TestViewModel) {
        model.addContext(context)
    }
    return model
}

fun <T : ViewModelProvider, V : ViewModel> T.get(
    modelClass: Class<V>,
    context: Context
): V {
    val model = get(modelClass)
    if (model is TestViewModel) {
        model.addContext(context)
    }
    return model
}

TestViewModel中添加如下的方法

class TestViewModel : ViewModel() {
    protected lateinit var context: Context
    open fun addContext(context: FragmentActivity) {
        this.context = context
    }

    open fun addContext(context: Context) {
        this.context = context
    }
}

使用方法

val viewModel = ViewModelProvider(this).get(TestViewModel::class.java, this)

#2.通过自定义ViewModelProvider.Factory

class CoreViewModelFactory(private val context: Context) : ViewModelProvider.Factory {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        try {
            for (constructor in modelClass.constructors) {
                if (arrayOf(Context::class.java).contentEquals(constructor.parameterTypes)) {
                    return (constructor as Constructor<T>).newInstance(context)
                }
            }
            return modelClass.newInstance()
        } catch (e: InstantiationException) {
            throw RuntimeException("Cannot create an instance of $modelClass", e)
        } catch (e: IllegalAccessException) {
            throw RuntimeException("Cannot create an instance of $modelClass", e)
        }
    }
}

关于这一块,仔细阅读ViewModelProvider的代码,会发现,里面同样提供了两三种的Factory。针对可以直接拥有contextAndroidViewModel,提供了ViewModelProvider.AndroidViewModelFactory,只是在引用的时候,不要再自己添加一遍了。

以下是你的TestViewModel

class TestViewModel(private val context: Context) : ViewModel() {
    init {
        L.i(" context $context ")
    }
}

使用方法

val viewModel = ViewModelProvider(this, CoreViewModelFactory(this)).get(TestViewModel::class.java)

以上两种方法也可以用来帮助你自定义一些你要传入的参数。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值