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

Android:飞行模式变化时如何从Broadcast Receiver调用ViewModel方法?

如何在飞行模式切换时调用ViewModel的Refresh()方法?

你的核心需求是监听系统飞行模式变化事件,触发ViewModel中的refresh()方法更新数据与UI。现有代码的问题在于广播接收器无法直接访问ViewModel实例,还可能引发内存泄漏,以下是优化后的实现方案:

步骤1:修改广播接收器,通过回调传递事件

将广播接收器改为通过回调接口通知外部事件,避免直接持有ViewModel引用:

class AirplaneModeChanged(private val onModeChanged: () -> Unit) : BroadcastReceiver() {

    override fun onReceive(context: Context?, intent: Intent?) {
        if (intent?.action == Intent.ACTION_AIRPLANE_MODE_CHANGED) {
            // 触发回调,通知外部飞行模式已变更
            onModeChanged.invoke()
        }
    }
}

步骤2:在Activity中关联广播接收器与ViewModel

在MainActivity中注册广播接收器时,传入回调逻辑直接调用ViewModel的refresh()方法,同时做好生命周期管理:

class MainActivity : ComponentActivity() {
    private val viewModel: MyViewModel by viewModels()
    private lateinit var airplaneModeReceiver: AirplaneModeChanged

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 初始化接收器,传入回调触发ViewModel的refresh
        airplaneModeReceiver = AirplaneModeChanged {
            viewModel.refresh()
        }
        // 注册广播接收器,指定不导出避免安全风险
        ContextCompat.registerReceiver(
            applicationContext,
            airplaneModeReceiver,
            IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED),
            ContextCompat.RECEIVER_NOT_EXPORTED
        )
    }

    override fun onDestroy() {
        super.onDestroy()
        // 销毁时注销接收器,防止内存泄漏
        unregisterReceiver(airplaneModeReceiver)
    }
}

步骤3:优化ViewModel的refresh方法(可选但推荐)

如果refresh()涉及数据库访问等耗时操作,必须在后台线程执行,同时用StateFlow/LiveData更新UI,符合MVVM架构规范:

import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch

class MyViewModel(application: Application) : AndroidViewModel(application) {
    // 用StateFlow暴露UI状态
    private val _uiData = MutableStateFlow<YourDataModel?>(null)
    val uiData = _uiData.asStateFlow()

    fun refresh() {
        viewModelScope.launch {
            // 在后台线程执行数据库访问
            val updatedData = fetchDataFromDatabase()
            // 更新UI状态
            _uiData.value = updatedData
        }
    }

    private suspend fun fetchDataFromDatabase(): YourDataModel {
        // 这里写具体的数据库查询逻辑
        return // 返回从数据库获取的数据
    }
}

额外说明

  • 若需要判断飞行模式的具体状态(开启/关闭),可以在广播接收器的onReceive中获取:
    val isAirplaneModeEnabled = intent?.getBooleanExtra("state", false) ?: false
    
  • 始终确保在Activity销毁时注销广播接收器,避免内存泄漏
  • 利用viewModelScope可以自动跟随ViewModel生命周期取消协程,不会因为Activity销毁导致异步任务继续执行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 08:49:57