我有一个名为“BatteryManagerHelper”的静态类,它通过 Intent.ACTION_BATTERY_CHANGED 意图监控电池状态。每次系统通知电池状态发生变化时,我的班级都会捕获变化,将新值存储在班级公共属性(充电、状态、健康..)中,然后引发事件“已更改”
公共静态事件操作已更改;
我项目中的每个 Activity 或 Class 都可以使用代码订阅此事件:
BatteryManagerHelper.Changed += BatteryManagerHelper_Changed;
private void BatteryManagerHelper_Changed()
{
imgBattery.SetImageResource(some_resource);
}
它工作正常。
但是,当 Activity 进入 OnPause() 或 OnDestory() 时,我想取消订阅 Change 事件,因此不再向我的 Activity 发出通知。
我试过了
BatteryManagerHelper.Changed -= BatteryManagerHelper_Changed;
和
BatteryManagerHelper.Changed -= null;
和
BatteryManagerHelper.Changed += null;
但似乎没有人工作。我在 Activity 中也得到了事件,已经从系统中销毁。
所以,第一个问题是:如何正确取消订阅事件?第二个问题是:为什么一个被销毁的activity可以继续接收事件?
注意:订阅和取消订阅代码放在 OnResume() 和 OnPause() 上。当活动暂停然后恢复时,我收到两个事件通知;在第一次暂停恢复时,我收到三个连续的通知,依此类推。似乎 += 正在添加一个新的事件侦听器,而 -= 无法删除侦听器,从而使以前的侦听器引用保持有效。
这是静态类代码。我使用了一个静态类,因此可以在代码中的任何位置访问它。静态类(显然)有一个用于 BroadcastReceiver 回调的子类的私有实例。
using Android.Content;
using Android.Os;
using System;
namespace MenuDroidApp
{
public static class BatteryManagerHelper
{
private static BatteryBroadcastReceiverHelper batteryBroadcastReceiver = null;
private static Intent batteryStatusIntent = null;
public static event Action Changed;
public enum HealthEnum
{
Unknown = 1, // BATTERY_HEALTH_UNKNOWN
Good, // BATTERY_HEALTH_GOOD
OverHeat, // BATTERY_HEALTH_OVERHEAT
Dead, // BATTERY_HEALTH_DEAD
OverVoltage, // BATTERY_HEALTH_OVER_VOLTAGE
UnspecifiedFailure, // BATTERY_HEALTH_UNSPECIFIED_FAILURE
Cold, // BATTERY_HEALTH_COLD
}
public enum PluggedEnum
{
NotPlugged = 0,
PluggedAC, // BATTERY_PLUGGED_AC
PluggedUSB, // BATTERY_PLUGGED_USB
PluggedWireless, // BATTERY_PLUGGED_WIRELESS
}
public enum StatusEnum
{
Unknown = 1, // BATTERY_STATUS_UNKNOWN
Charging, // BATTERY_STATUS_CHARGING
Discharging, // BATTERY_STATUS_DISCHARGING
NotCharging, // BATTERY_STATUS_NOT_CHARGING
Full, // BATTERY_STATUS_FULL
}
public static int Charge { get; set; }
public static StatusEnum Status { get; set; }
public static PluggedEnum Plugged { get; set; }
public static HealthEnum Health { get; set; }
public static bool Present { get; set; }
public static string Technology { get; set; }
public static int Temperature { get; set; }
public static int Voltage { get; set; }
public static int IconResID { get; set; }
static BatteryManagerHelper()
{
batteryBroadcastReceiver = new BatteryBroadcastReceiverHelper();
batteryBroadcastReceiver.Changed += batteryBroadcastReceiver_Changed;
}
private static void batteryBroadcastReceiver_Changed()
{
if (Changed != null) Changed();
}
public static void Start()
{
batteryStatusIntent = Common.ApplicationContext.RegisterReceiver(batteryBroadcastReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
batteryBroadcastReceiver.GetBatteryInfo(batteryStatusIntent);
}
public static void Stop()
{
Common.ApplicationContext.UnregisterReceiver(batteryBroadcastReceiver);
batteryStatusIntent = null;
}
private class BatteryBroadcastReceiverHelper : BroadcastReceiver
{
public event Action Changed;
public override void OnReceive(Context context, Intent intent)
{
GetBatteryInfo(intent);
}
public void GetBatteryInfo(Intent intent)
{
BatteryManagerHelper.Charge = intent.GetIntExtra(BatteryManager.EXTRA_LEVEL, -1);
BatteryManagerHelper.Status = (StatusEnum)intent.GetIntExtra(BatteryManager.EXTRA_STATUS, 0);
BatteryManagerHelper.Health = (HealthEnum)intent.GetIntExtra(BatteryManager.EXTRA_HEALTH, 0);
BatteryManagerHelper.Plugged = (PluggedEnum)intent.GetIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
BatteryManagerHelper.Present = intent.GetBooleanExtra(BatteryManager.EXTRA_PRESENT, false);
BatteryManagerHelper.Technology = intent.GetStringExtra(BatteryManager.EXTRA_TECHNOLOGY);
BatteryManagerHelper.Temperature = intent.GetIntExtra(BatteryManager.EXTRA_TEMPERATURE, -1);
BatteryManagerHelper.Voltage = intent.GetIntExtra(BatteryManager.EXTRA_VOLTAGE, -1);
BatteryManagerHelper.IconResID = intent.GetIntExtra(BatteryManager.EXTRA_ICON_SMALL, -1);
if (Changed != null) Changed();
}
}
}
}
这是我的片段中的代码(这个片段是系统工具栏的替代品,我的应用是全屏的),但您也可以在经典的 Activity 类中尝试 OnResume() 和 OnPause() 事件
public override void OnAttach(Activity activity)
{
BatteryManagerHelper.Changed += BatteryManagerHelper_Changed;
}
public override void OnDetach()
{
BatteryManagerHelper.Changed -= BatteryManagerHelper_Changed;
}
private void BatteryManagerHelper_Changed()
{
imgBattery.SetImageResource(some_resource_id);
}
好的,我在订阅/取消订阅事件时尝试了不同的方法:
private Action batteryManager_Callback = null;
public override void OnResume()
{
base.OnResume();
batteryManager_Callback = new Action(BatteryManagerHelper_Changed);
BatteryManagerHelper.Changed += batteryManager_Callback;
}
public override void OnPause()
{
base.OnPause();
BatteryManagerHelper.Changed -= batteryManager_Callback;
}
private void BatteryManagerHelper_Changed()
{
imgBattery.SetImageResource(some_res_id);
}
现在它工作正常。我为每个 OnResume 活动事件使用一个新的委托对象,并使用该委托订阅 BatteryManager 事件。委托引用也存储在私有类成员上。当我想取消订阅时,我使用在 OnResumed() 中创建的相同原始委托引用,并且我确信将从事件侦听器队列中删除相同的一个特定委托。
所以看起来原始代码
public override void OnAttach(Activity activity)
{
BatteryManagerHelper.Changed += BatteryManagerHelper_Changed;
}
public override void OnDetach()
{
BatteryManagerHelper.Changed -= BatteryManagerHelper_Changed;
}
回调函数 BatteryManagerHelper_Changed() 的引用在 += 的时刻和 -= 的时刻是不同的。但是 Activity 类实例是相同的,这很奇怪.. 这个 C#/.NET 环境中的示例运行良好。
关于这种行为的任何想法?这是设计正确的吗?
谢谢