Android广播接收器未在电源切换时刷新电池数据问题求助
问题分析与解决方案
哎,我明白为啥电源切换时数据不刷新了!你现在的代码只在Fragment创建的时候调用了一次retrieveBatteryData获取电源状态,之后不管电源怎么插拔,都没有任何机制去监听这个状态变化并触发界面更新。虽然ACTION_BATTERY_CHANGED是系统粘性广播,但你只是一次性拿了当前状态,没注册接收器盯着后续的变化呀。
下面给你一步步解决这个问题:
核心思路
- 注册
BroadcastReceiver监听ACTION_BATTERY_CHANGED广播,每次电源状态变化时都会收到通知 - 在Fragment生命周期中正确注册/注销接收器,避免内存泄漏
- 复用现有RecyclerView适配器,更新数据后通知界面刷新,不用每次都新建适配器
修改后的代码示例
更新BatteryFragment
public class BatteryFragment extends Fragment { FragmentBatteryBinding fragmentBatteryBinding; BatteryFragmentVm batteryFragmentVm; List<PojoMain> batteryData; RecyclerAdapter recyclerDeviceAdapter; // 定义电池状态广播接收器 private BroadcastReceiver batteryStatusReceiver; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); fragmentBatteryBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_battery, container, false); batteryFragmentVm = new BatteryFragmentVm(); fragmentBatteryBinding.setBatteryVm(batteryFragmentVm); // 初始化数据列表与适配器 batteryData = new ArrayList<>(); recyclerDeviceAdapter = new RecyclerAdapter(batteryData, requireContext()); fragmentBatteryBinding.batteryRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext())); fragmentBatteryBinding.batteryRecyclerView.setAdapter(recyclerDeviceAdapter); // 初始化获取一次电池数据 refreshBatteryStatus(); // 初始化广播接收器:收到状态变化时刷新数据 batteryStatusReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { refreshBatteryStatus(); } }; return fragmentBatteryBinding.getRoot(); } // 修正后的电源来源判断方法(注意区分充电类型和电池状态) private String getPowerSource(Context context) { Intent intent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); int pluggedType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); if (pluggedType == BatteryManager.BATTERY_PLUGGED_AC) { return "Plugged AC"; } else if (pluggedType == BatteryManager.BATTERY_PLUGGED_USB) { return "Plugged USB"; } else if (pluggedType == BatteryManager.BATTERY_PLUGGED_WIRELESS) { return "Plugged Wireless"; } else { // 未连接任何充电设备,处于放电状态 return "Discharging"; } } // 刷新电池数据并更新界面 private void refreshBatteryStatus() { batteryData.clear(); batteryData.add(new PojoMain("Power Source", getPowerSource(requireContext()))); // 通知适配器数据变化 recyclerDeviceAdapter.notifyDataSetChanged(); } @Override public void onResume() { super.onResume(); // 注册广播接收器 IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); requireContext().registerReceiver(batteryStatusReceiver, filter); } @Override public void onPause() { super.onPause(); // 注销接收器,防止内存泄漏 requireContext().unregisterReceiver(batteryStatusReceiver); } }
优化BatteryFragmentVm(可选,改用LiveData更贴合Android生命周期)
ViewModel不应该持有Context引用,改用LiveData来管理数据会更安全:
public class BatteryFragmentVm extends ViewModel { private final MutableLiveData<List<PojoMain>> batteryDataLiveData = new MutableLiveData<>(); public void updateBatteryData(List<PojoMain> newData) { batteryDataLiveData.postValue(newData); } public LiveData<List<PojoMain>> getBatteryDataLiveData() { return batteryDataLiveData; } }
然后在Fragment的onCreateView里添加观察者:
batteryFragmentVm.getBatteryDataLiveData().observe(getViewLifecycleOwner(), data -> { batteryData.clear(); batteryData.addAll(data); recyclerDeviceAdapter.notifyDataSetChanged(); });
对应的refreshBatteryStatus方法改成:
private void refreshBatteryStatus() { List<PojoMain> newData = new ArrayList<>(); newData.add(new PojoMain("Power Source", getPowerSource(requireContext()))); batteryFragmentVm.updateBatteryData(newData); }
关键注意点
- 修正了原代码中的逻辑错误:
BATTERY_STATUS_DISCHARGING是电池的工作状态,而EXTRA_PLUGGED返回的是充电类型,两者不要混淆 - 广播接收器必须在
onPause中注销,否则会导致内存泄漏 - 复用RecyclerView适配器比每次新建更高效,避免不必要的视图重建
内容的提问来源于stack exchange,提问作者Ghimire
相关产品推荐
相关产品推荐

