如何避免配置变更时Activity的onCreate重复调用ViewModel的API?
避免配置变更时重复调用API的几种方案
方案一:利用ViewModel的生命周期标记请求状态
ViewModel在配置变更(如切换语言)时不会被销毁,因此可以在ViewModel内部维护一个请求状态标记,确保API仅被调用一次。
修改后的ViewModel代码:
class MainViewModel : ViewModel() { // 标记API是否已调用过 private var hasCalledApi = false fun callApi() { if (!hasCalledApi) { // 执行实际的API请求逻辑 // 例如:retrofitService.fetchData() println("API请求执行") // 标记为已调用 hasCalledApi = true } } }
Activity代码无需修改,每次重建后拿到的是同一个ViewModel实例,hasCalledApi会保持之前的状态,不会重复触发请求。
方案二:通过Activity的savedInstanceState判断首次创建
当Activity因配置变更重建时,savedInstanceState参数不为null;而应用启动时首次创建Activity,savedInstanceState为null。可以利用这一点控制API调用时机:
修改后的Activity代码:
class MainActivity : AppCompatActivity() { private val viewmodel: MainViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 仅在首次创建Activity时调用API if (savedInstanceState == null) { viewmodel.callApi() } setContent { // UI代码 } } }
注意:如果Activity因系统内存不足被销毁后重建,savedInstanceState也会不为null,此时不会触发API调用。若需要这种场景下重新调用API,该方案不适用。
方案三:持久化标记(确保应用重启后也仅调用一次)
如果需要API在应用整个生命周期内仅调用一次(包括重启应用后),可以用SharedPreferences持久化标记状态:
1. 修改ViewModel,依赖SharedPreferences
class MainViewModel(private val sharedPreferences: SharedPreferences) : ViewModel() { private val API_CALL_KEY = "has_called_api" fun callApi() { val hasCalled = sharedPreferences.getBoolean(API_CALL_KEY, false) if (!hasCalled) { // 执行API请求逻辑 println("API请求执行") // 持久化标记 sharedPreferences.edit().putBoolean(API_CALL_KEY, true).apply() } } }
2. 创建ViewModel工厂类,传入SharedPreferences
class MainViewModelFactory(private val sharedPreferences: SharedPreferences) : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { if (modelClass.isAssignableFrom(MainViewModel::class.java)) { @Suppress("UNCHECKED_CAST") return MainViewModel(sharedPreferences) as T } throw IllegalArgumentException("未知的ViewModel类") } }
3. 在Activity中使用工厂获取ViewModel
class MainActivity : AppCompatActivity() { private val viewmodel: MainViewModel by viewModels { MainViewModelFactory(getSharedPreferences("app_settings", MODE_PRIVATE)) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) viewmodel.callApi() setContent { // UI代码 } } }
这样即使应用重启,SharedPreferences中的标记依然存在,API只会被调用一次。
内容的提问来源于stack exchange,提问作者user7029573
相关产品推荐
相关产品推荐

