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

Fragment切换场景下的Executor生命周期管理问题

解决方案

核心问题在于测试状态和Executor实例绑定在Fragment上,而Fragment会随页面切换销毁重建,导致状态丢失和重复创建实例。正确的做法是将测试逻辑和状态托管到ViewModel中,其生命周期与所属Activity一致,不受Fragment重建影响。

步骤1:重构HomeViewModel,托管测试逻辑和状态

修改HomeViewModel,将测试状态、Executor、任务实例移至其中,并提供启动/停止测试的方法:

import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledFuture
import java.util.concurrent.TimeUnit

class HomeViewModel(application: Application) : AndroidViewModel(application) {
    // 标记测试是否正在运行的LiveData,用于Fragment观察更新UI
    private val _isTestRunning = MutableLiveData<Boolean>(false)
    val isTestRunning: LiveData<Boolean> = _isTestRunning

    private val scheduledExecutor = Executors.newSingleThreadScheduledExecutor()
    private var testFuture: ScheduledFuture<*>? = null

    fun toggleTest() {
        if (_isTestRunning.value == true) {
            // 停止测试
            testFuture?.cancel(true)
            _isTestRunning.value = false
        } else {
            // 启动测试
            val st = ScheduledTests() // 你的测试任务类
            testFuture = scheduledExecutor.scheduleAtFixedRate(st, 0, 5, TimeUnit.SECONDS)
            _isTestRunning.value = true
        }
    }

    // ViewModel销毁时关闭Executor,避免内存泄漏
    override fun onCleared() {
        super.onCleared()
        testFuture?.cancel(true)
        scheduledExecutor.shutdown()
    }
}

步骤2:修改HomeFragment,依赖ViewModel控制逻辑

移除Fragment中与测试相关的局部变量,改为通过ViewModel获取状态和调用方法:

package com.giorgio.roamingqosapp.ui.home

import ...

class HomeFragment : Fragment() {
    private var _binding: FragmentHomeBinding? = null
    private val binding get() = _binding!!
    private lateinit var homeViewModel: HomeViewModel

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        // 使用Activity级别的ViewModelProvider,确保ViewModel与Activity生命周期绑定
        homeViewModel = ViewModelProvider(requireActivity())[HomeViewModel::class.java]
        _binding = FragmentHomeBinding.inflate(inflater, container, false)
        val root: View = binding.root

        // 初始化运营商、漫游状态显示(保留原有逻辑)
        val tm = requireActivity().getSystemService(Activity.TELEPHONY_SERVICE) as TelephonyManager
        val SIMOperatorName = tm.simOperatorName
        val isRoaming = tm.isNetworkRoaming

        SIMOperatorName?.let {
            binding.registeredOperator.text = getString(R.string.registered_operator, it)
        }
        binding.roaming.text = getString(
            R.string.roaming,
            if (isRoaming) "Roaming" else "Home"
        )
        binding.registeredImageView.setImageDrawable(
            AppCompatResources.getDrawable(requireContext(), R.drawable.led_verde)
        )

        // 初始化图标点击事件
        binding.testsOn.setOnClickListener { homeViewModel.toggleTest() }
        binding.testsOff.setOnClickListener { homeViewModel.toggleTest() }

        // 观察测试状态,自动更新UI
        homeViewModel.isTestRunning.observe(viewLifecycleOwner) { isRunning ->
            if (isRunning) {
                binding.testsOn.visibility = View.GONE
                binding.testsOff.visibility = View.VISIBLE
            } else {
                binding.testsOn.visibility = View.VISIBLE
                binding.testsOff.visibility = View.GONE
            }
        }

        return root
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

关键说明

  1. ViewModel的作用:ViewModel在Activity存活期间始终存在,Fragment切换时不会被销毁,因此测试状态和Executor实例得以保留,避免重复创建。
  2. LiveData状态观察:Fragment通过观察ViewModel中的isTestRunning LiveData,在状态变化时自动更新图标显示,确保返回HomeFragment时UI与实际测试状态一致。
  3. Executor生命周期管理:在ViewModel的onCleared方法中关闭Executor并取消任务,避免APP退出后出现内存泄漏。
  4. 避免重复实例:所有测试启动/停止操作都通过ViewModel统一处理,确保同一时间只有一个测试任务在运行。

内容的提问来源于stack exchange,提问作者Giorgio Torassa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 05:55:06