Android MVVM架构下应用从后台切至前台时如何调用API
Android MVVM架构下后台切前台调用API的实现方法
一、依赖准备
确保项目引入Jetpack Lifecycle相关依赖,用于监听应用全局生命周期:
dependencies { implementation "androidx.lifecycle:lifecycle-process:2.6.2" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2" implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.2" // Retrofit(用于API调用,按需引入) implementation "com.squareup.retrofit2:retrofit:2.9.0" implementation "com.squareup.retrofit2:converter-gson:2.9.0" }
二、实现全局前后台状态监听
通过ProcessLifecycleOwner监听应用全局的前后台切换状态,封装成单例管理器:
class AppForegroundStateManager private constructor() : LifecycleObserver { private val _isForeground = MutableLiveData<Boolean>() val isForeground: LiveData<Boolean> = _isForeground @OnLifecycleEvent(Lifecycle.Event.ON_START) fun onEnterForeground() { _isForeground.postValue(true) } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) fun onEnterBackground() { _isForeground.postValue(false) } companion object { val instance: AppForegroundStateManager by lazy { AppForegroundStateManager() } } }
在自定义Application类中注册该观察者:
class MyApp : Application() { override fun onCreate() { super.onCreate() ProcessLifecycleOwner.get().lifecycle.addObserver(AppForegroundStateManager.instance) } }
三、MVVM分层实现API调用
1. Repository层(数据请求)
负责实际的API调用逻辑,与ViewModel解耦:
// Retrofit接口定义 interface ApiService { @GET("api/latest-data") suspend fun fetchLatestData(): ApiResponse } // Repository实现 class DataRepository(private val apiService: ApiService) { suspend fun getLatestData(): ApiResponse { return apiService.fetchLatestData() } }
2. ViewModel层(业务逻辑处理)
观察前后台状态,在应用切前台时触发API请求,并通过LiveData通知View层:
// 封装API请求状态的密封类 sealed class Resource<out T> { object Loading : Resource<Nothing>() data class Success<out T>(val data: T) : Resource<T>() data class Error(val message: String) : Resource<Nothing>() } class MainViewModel(private val repo: DataRepository) : ViewModel() { private val _apiResult = MutableLiveData<Resource<ApiResponse>>() val apiResult: LiveData<Resource<ApiResponse>> = _apiResult private var lastRequestTime = 0L private val MIN_REQUEST_INTERVAL = 5 * 60 * 1000 // 5分钟防重复请求 init { observeForegroundState() } private fun observeForegroundState() { AppForegroundStateManager.instance.isForeground.observeForever { isForeground -> if (isForeground) { val currentTime = System.currentTimeMillis() if (currentTime - lastRequestTime > MIN_REQUEST_INTERVAL) { lastRequestTime = currentTime fetchData() } } } } private fun fetchData() = viewModelScope.launch { _apiResult.postValue(Resource.Loading) try { val data = repo.getLatestData() _apiResult.postValue(Resource.Success(data)) } catch (e: Exception) { _apiResult.postValue(Resource.Error(e.message ?: "数据请求失败")) } } override fun onCleared() { super.onCleared() // 移除观察者,避免内存泄漏 AppForegroundStateManager.instance.isForeground.removeObserver(::observeForegroundState) } }
3. View层(UI更新)
在Activity/Fragment中观察ViewModel的LiveData,根据请求状态更新UI:
class MainActivity : AppCompatActivity() { private lateinit var viewModel: MainViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 初始化ViewModel(可通过DI框架注入Repository,示例用默认Provider) val apiService = Retrofit.Builder() .baseUrl("https://your-api-domain.com/") .addConverterFactory(GsonConverterFactory.create()) .build() .create(ApiService::class.java) val repo = DataRepository(apiService) viewModel = ViewModelProvider(this, object : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { return MainViewModel(repo) as T } })[MainViewModel::class.java] // 观察API请求结果 viewModel.apiResult.observe(this) { resource -> when (resource) { Resource.Loading -> showLoadingDialog() is Resource.Success -> { dismissLoadingDialog() updateUI(resource.data) } is Resource.Error -> { dismissLoadingDialog() Toast.makeText(this, resource.message, Toast.LENGTH_SHORT).show() } } } } // 省略UI操作方法 private fun showLoadingDialog() { /* ... */ } private fun dismissLoadingDialog() { /* ... */ } private fun updateUI(data: ApiResponse) { /* ... */ } }
四、关键注意事项
- 防重复请求:通过时间间隔判断避免短时间内重复调用API,减少服务器压力。
- 内存泄漏防护:ViewModel中使用
observeForever后,必须在onCleared方法中移除观察者。 - 异常处理:API调用时捕获网络异常、解析异常等,通过
Resource.Error状态通知View层。 - 权限检查:确保应用拥有网络权限,可在请求前添加网络状态判断。
内容的提问来源于stack exchange,提问作者Andyson
相关产品推荐
相关产品推荐

