You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android Library模块中正确使用AndroidViewModel

Library模块无法获取Application初始化ViewModel的解决方案

问题根因

Android Library模块本身没有独立的Application生命周期,所有运行时上下文都来自依赖该Library的宿主Application模块,因此无法在Library内部直接获取Application实例,导致自定义Factory无法初始化,触发ViewModel创建失败崩溃。

方案1:显式初始化入口(推荐,可控性最高)

在Library内部提供全局初始化方法,要求宿主App集成时在自身Application中传入实例完成初始化:

  1. Library内部编写全局配置单例:
object LibraryCore {
    private var _application: Application? = null
    val application: Application
        get() = _application ?: throw IllegalStateException("请先调用LibraryCore.init(application)完成Library初始化")

    // 宿主App在Application.onCreate中调用该方法
    fun init(application: Application) {
        _application = application
    }
}
  1. 宿主App的Application类中完成初始化:
class HostApp : Application() {
    override fun onCreate() {
        super.onCreate()
        // 初始化依赖的Library
        LibraryCore.init(this)
    }
}
  1. 后续Library内任意需要Application的场景直接调用LibraryCore.application即可,初始化ViewModel Factory示例:
val viewModel = ViewModelProvider(
    this, 
    LanguageViewModelProvider(LibraryCore.application)
)[LanguageViewModel::class.java]

方案2:自动初始化(无需宿主手动操作)

如果希望降低宿主集成成本,可以通过自定义ContentProvider自动获取上下文完成初始化,无需宿主额外编码:

  1. 复用方案1中的LibraryCore单例,新增初始化用ContentProvider:
class LibraryInitProvider : ContentProvider() {
    override fun onCreate(): Boolean {
        (context?.applicationContext as? Application)?.let {
            LibraryCore.init(it)
        }
        return true
    }

    // 其余方法无需实现,返回默认值即可
    override fun query(uri: Uri, projection: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, sortOrder: String?): Cursor? = null
    override fun getType(uri: Uri): String? = null
    override fun insert(uri: Uri, values: ContentValues?): Uri? = null
    override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?) = 0
    override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<out String>?) = 0
}
  1. 在Library模块的AndroidManifest.xml中注册该Provider:
<provider
    android:name=".LibraryInitProvider"
    android:authorities="${applicationId}.library_init_provider"
    android:exported="false" />

Library集成到宿主后会自动触发ContentProvider创建,拿到全局Application实例完成初始化。

方案3:宿主直接传参实例化

如果不想修改Library内部逻辑,可以直接要求宿主在实例化ViewModel时传入自身Application:

// 宿主Activity/Fragment内初始化代码示例
val factory = LanguageViewModelProvider(applicationContext as Application)
val viewModel = ViewModelProvider(this, factory)[LanguageViewModel::class.java]

注意事项

上述方案中持有的都是全局Application实例,不会产生内存泄漏问题;如果使用显式初始化方案,建议添加初始化状态判断,避免未初始化直接调用导致崩溃。

内容的提问来源于stack exchange,提问作者Ahmet B.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 16:09:02