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

Android开发:为何要在ViewModel中执行网络请求?配置变化时请求重复问题解惑

Why Perform Network Requests in ViewModel (And Why Your Requests Still Repeat on Configuration Changes)

Great question! Let's unpack this—first, the extra reasons to put network calls in ViewModel, then why you're still seeing repeated API calls when rotating your device.

Additional Reasons to Run Network Requests in ViewModel

Beyond retaining data across configuration changes, there are several key benefits:

  • Separation of concerns: Activities/Fragments should focus solely on UI rendering and user interactions. Shifting network logic (and other business logic) to ViewModel keeps your UI code clean, maintainable, and easier to debug. No more cluttering your Fragment with Retrofit setup or error handling—let the ViewModel handle that heavy lifting.
  • Lifecycle safety: ViewModels outlive temporary UI destructions (like rotations) but are cleared when the UI is permanently destroyed (e.g., when the user navigates away). This means you can run network requests without worrying about memory leaks (as long as you use lifecycle-aware scopes like viewModelScope for coroutines).
  • Data sharing across UI components: If multiple Fragments in the same Activity share a ViewModel, you can reuse the network request result across all of them. No need to duplicate API calls for each Fragment—saves bandwidth and keeps data consistent.
  • Easier testing: ViewModels don't depend on UI components, so writing unit tests for your network logic is straightforward. You can mock your repository layer and validate how the ViewModel handles success, errors, and loading states without spinning up an Activity or Fragment.

Why Your API Calls Still Repeat on Configuration Changes

Here's the thing: ViewModel doesn't automatically prevent repeated requests out of the box. The issue likely comes from how you're triggering the request. For example:

  • If you call the ViewModel's fetch method in your Fragment's onViewCreated() (or similar lifecycle method), that method runs every time the Fragment is recreated after a rotation—so it re-triggers the request.
  • If you mistakenly reinitialize the ViewModel logic on Fragment recreation (though ViewModels are supposed to be reused), that could also cause duplicate calls.

Fixes to Stop Repeated Requests

You need to add state tracking in your ViewModel to avoid redundant calls. Here are a few common approaches:

  1. Cache the result and track loading state
    Add variables to store the cached result and whether a request is already in progress:

    private val _data = MutableLiveData<Result<MyData>>()
    val data: LiveData<Result<MyData>> = _data
    
    private var cachedResult: Result<MyData>? = null
    private var isRequestInProgress = false
    
    fun fetchData() {
        // Return cached result if available
        cachedResult?.let {
            _data.value = it
            return
        }
        // Don't start a new request if one is already running
        if (isRequestInProgress) return
    
        isRequestInProgress = true
        viewModelScope.launch {
            try {
                val freshData = repository.fetchMyData()
                cachedResult = Result.Success(freshData)
                _data.value = cachedResult
            } catch (e: Exception) {
                _data.value = Result.Error(e)
            } finally {
                isRequestInProgress = false
            }
        }
    }
    

    Now, when your Fragment calls fetchData() after a rotation, it'll either use the cached result or skip the request if one's already underway.

  2. Use Kotlin Flow with stateIn
    If you're using Flow instead of LiveData, convert your request Flow to a StateFlow that retains its state across subscriptions:

    val data: StateFlow<Result<MyData>> = repository.fetchMyDataFlow()
        .stateIn(
            scope = viewModelScope,
            started = SharingStarted.WhileSubscribed(5000), // Keep subscription alive for 5s after UI disconnects
            initialValue = Result.Loading
        )
    

    The WhileSubscribed(5000) ensures that if the UI is recreated within 5 seconds (like during a rotation), the Flow doesn't re-execute the network request—it just emits the latest state to the new subscriber.

  3. Avoid triggering requests in Fragment lifecycle methods
    Instead of calling fetchData() in onViewCreated(), trigger it only when necessary—like when the user taps a button, or when the screen first loads and there's no cached data.

Wrap-Up

ViewModel is an ideal place for network requests thanks to its lifecycle benefits and separation of concerns, but you need to handle request state manually to prevent duplicates on configuration changes. Adding caching or using Flow's state retention will fix the repeated API calls you're seeing.

内容的提问来源于stack exchange,提问作者Sparsh Dutta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 14:32:26