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

手动依赖注入下ViewModel获取MyApplication实例为空引发NPE求助

问题排查:获取MyApplication实例为空导致空指针异常

我采用手动依赖注入方式编写了PreferenceViewModel,用于从MyApplication中获取用户仓库,但运行时抛出错误:java.lang.NullPointerException: null cannot be cast to non-null type MyApplication。已在Manifest中正确配置Application名称,相关代码如下:

PreferenceViewModel代码

class PreferenceViewModel(
    private val prefRepo: PreferenceRepository
) : ViewModel() {

    // 其他功能代码

    companion object {
        val Factory: ViewModelProvider.Factory = viewModelFactory {
            initializer {
                val application = (this[APPLICATION_KEY] as MyApplication)
                UserViewModel(application.prefRepository)
            }
        }
    }
}

MyApplication代码

private const val USER_PREFERENCE_NAME = "user_preference"

private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(
    name = USER_PREFERENCE_NAME
)

class MyApplication: Application() {

    lateinit var prefRepository: PreferenceRepository

    override fun onCreate() {
        super.onCreate()

        prefRepository = PreferenceRepository(dataStore)
    }

}

Compose函数获取ViewModel的方式

@Composable
fun PreferencePage(
    navController: NavHostController,

    prefViewModel: PreferenceViewModel = viewModel(
        factory = PreferenceViewModel.Factory
    )
) {
    // 实现代码
}

MainActivity代码

class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            AppTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    val navController = rememberNavController()
                    NavHost(navController = navController, startDestination = "PreferencePage") {
                        composable("PreferencePage") {
                            PreferencePage(navController = navController, viewModel)
                        }
                        // 其他代码
                    }
                }
            }
        }
    }
}

问题原因及修复方案

1. ViewModel工厂返回错误实例

在PreferenceViewModel.Factory的初始化逻辑中,你创建并返回的是UserViewModel,而非当前类PreferenceViewModel,这会直接打乱ViewModel的初始化流程,间接导致Application实例获取异常。

修复后的工厂代码:

companion object {
    val Factory: ViewModelProvider.Factory = viewModelFactory {
        initializer {
            val application = (this[APPLICATION_KEY] as MyApplication)
            // 替换为当前ViewModel类
            PreferenceViewModel(application.prefRepository)
        }
    }
}

2. NavHost中传递未定义的ViewModel变量

在MainActivity的NavHost代码块里,你直接传递了未定义的viewModel变量给PreferencePage,这会绕过Compose的ViewModel初始化机制,导致无法正确关联上下文获取Application实例。

修复后的NavHost代码:

NavHost(navController = navController, startDestination = "PreferencePage") {
    composable("PreferencePage") {
        // 移除多余的viewModel参数,让Compose函数内部自行初始化ViewModel
        PreferencePage(navController = navController)
    }
    // 其他代码
}

3. 二次确认Manifest配置

虽然你已声明配置正确,仍需再次检查AndroidManifest.xml的application标签是否正确指定自定义Application类:

<application
    android:name=".MyApplication"
    <!-- 其他属性 -->
    >
    <!-- 组件声明 -->
</application>

4. 优化:避免强制类型转换风险

可以给强转增加空判断,提前抛出明确异常:

val application = this[APPLICATION_KEY] as? MyApplication 
    ?: throw IllegalStateException("MyApplication未正确初始化,请检查Manifest配置")

内容的提问来源于stack exchange,提问作者qa30m

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 08:14:58