手动依赖注入下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
相关产品推荐
相关产品推荐

