广播接收器 → Flow + Lifecycle
老写法(Java + BroadcastReceiver)
java
private BroadcastReceiver batteryReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
tvBattery.setText("电量:" + level + "%");
}
};
@Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(batteryReceiver, filter);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(batteryReceiver);
}
问题在哪里
register/unregister 必须在正确的生命周期成对调用,时机一错就崩。每个广播接收器都要写注册逻辑和解注册逻辑,多个广播到处都是散落的 IntentFilter。
新写法(Flow + Lifecycle)
kotlin
// 封装为 Flow
fun batteryLevelFlow(context: Context): Flow<Int> = callbackFlow {
val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
trySend(level)
}
}
context.registerReceiver(receiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
awaitClose { context.unregisterReceiver(receiver) }
}
// 使用 --- 自动绑定生命周期
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
batteryLevelFlow(this@MainActivity).collect { level ->
tvBattery.text = "电量:$level%"
}
}
}
一句话注意
callbackFlow 内部 registerReceiver,awaitClose 里 unregisterReceiver,生命周期完全自动绑定,不需要手动 register/unregister。repeatOnLifecycle(STARTED) 确保前台才收集、后台自动取消,和 onResume/onPause 的注册时机语义一致。
Intent.ACTION_BATTERY_CHANGED 这种粘性广播不能用 context.registerReceiver 注册结果返回 null 的问题------因为它是粘性广播,即使是首次注册也会立刻收到回调,没有问题。但注意这个广播不能通过 manifest 静态注册,只能动态注册。
Java Android 老项目迁移系列,持续更新中。