使用Hilt传递运行时参数实例化ViewModel并在init块触发接口请求
解决方案
下面提供两种可落地的实现方式,可根据你的业务需求选择:
方案一:最简实现(推荐大部分场景使用)
不需要修改ViewModel构造参数,也无需自定义工厂,直接在Activity获取到授权码后调用ViewModel的方法即可,逻辑清晰维护成本低:
@AndroidEntryPoint class MainActivity : ComponentActivity() { private val viewModel : MainActivityViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 提取授权码 val authCode = intent.data?.getQueryParameter("code") authCode?.let { viewModel.getAccessToken(it) } ?: run { // 自行处理授权码为空的异常逻辑,比如跳转授权页、提示错误等 } // 其他初始化逻辑 } }
方案二:通过Hilt辅助注入实现构造传参(满足init块调用需求)
如果你确实需要在ViewModel的init初始化块中执行请求逻辑,可以使用Hilt提供的辅助注入(Assisted Inject)能力传递动态参数:
步骤1:改造ViewModel定义
// 声明辅助工厂 @HiltViewModel(assistedFactory = MainActivityViewModel.Factory::class) class MainActivityViewModel @AssistedInject constructor( private val repository: AuthRepository, // 动态参数加@Assisted注解 @Assisted private val authCode: String ) : ViewModel() { interface Factory { fun create(authCode: String): MainActivityViewModel } init { // 初始化阶段直接调用请求方法 getAccessToken(authCode) } fun getAccessToken(authCode: String) { // 原有请求逻辑 } }
步骤2:改造Activity中ViewModel的获取逻辑
@AndroidEntryPoint class MainActivity : ComponentActivity() { private val viewModel : MainActivityViewModel by viewModels { object : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { val authCode = intent.data?.getQueryParameter("code") ?: error("缺少必要的授权码参数") // 调用Hilt辅助工厂传入授权码生成ViewModel实例 return hiltViewModelFactory<MainActivityViewModel, MainActivityViewModel.Factory>( factoryClass = MainActivityViewModel.Factory::class ) { factory -> factory.create(authCode) } as T } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 其他初始化逻辑 } }
关于SavedStateHandle的疑问解答
默认情况下SavedStateHandle只能读取Intent的extras Bundle中的数据,无法直接读取intent.data里的查询参数。如果你想通过SavedStateHandle传递参数,还是需要先在Activity中提取出授权码后手动存入SavedStateHandle,本质和方案一逻辑一致,没有额外优势,因此不推荐。
内容的提问来源于stack exchange,提问作者Shadow_Land
相关产品推荐
相关产品推荐

