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

如何避免配置变更时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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 17:37:38