如何从广播接收器访问 Activity 的任何控件。不使用“静态”
Posted
技术标签:
【中文标题】如何从广播接收器访问 Activity 的任何控件。不使用“静态”【英文标题】:How to access any control of an Activity from a broadcast receiver. Without using "static" 【发布时间】:2020-02-01 06:16:09 【问题描述】:我想从广播接收器访问活动的控件,而不使用“静态”或在它们之间传递任何数据。我只想像在静态中一样直接访问它,但没有将任何类定义为静态。
在此示例中,我尝试从广播接收器更改 TextView 控件的文本值。
namespace App2
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
private BluetoothManager bluetoothManager;
private BluetoothAdapter bluetoothAdapter;
private BluetoothDeviceReceiver _receiver;
private TextView currentCharacterName;
int count = 0;
protected override void OnCreate(Bundle savedInstanceState)
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
Button ChangeTextButton = FindViewById<Button>(Resource.Id.button1);
currentCharacterName = FindViewById<TextView>(Resource.Id.textView1);
ChangeTextButton.Click += delegate
currentCharacterName.Text = string.Format("0 clicks!", count++);
;
var appContext = Application.Context;
bluetoothManager = (BluetoothManager)appContext.GetSystemService(BluetoothService);
bluetoothAdapter = bluetoothManager.Adapter;
if (bluetoothAdapter == null || !bluetoothAdapter.IsEnabled)
bluetoothManager.Adapter.Enable();
_receiver = new BluetoothDeviceReceiver();
RegisterReceiver(_receiver, new IntentFilter(BluetoothDevice.ActionFound));
bluetoothAdapter.StartDiscovery();
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] android.Content.PM.Permission[] grantResults)
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
private class BluetoothDeviceReceiver : BroadcastReceiver
public override void OnReceive(Context context, Intent intent)
var action = intent.Action;
TextView currentCharacterName = MainActivity.FindViewById<TextView>(Resource.Id.textView1);
if (action != BluetoothDevice.ActionFound)
return;
// Get the device
var device = (BluetoothDevice)intent.GetParcelableExtra(BluetoothDevice.ExtraDevice);
if (device.BondState != Bond.Bonded)
Console.WriteLine($"Found device with name: device.Name and MAC address: device.Address");
问题出现在这里
TextView currentCharacterName = MainActivity.FindViewById<TextView>(Resource.Id.textView1);
错误 CS0120 非静态字段、方法或属性需要对象引用
它需要什么样的参考? MainActivity 不是参考吗?周围还有其他 MainActivity 吗?我在 MainActivity 中定义了这个接收器,所以每当 MainActivity 获得一个实例时,这个接收器就属于那个实例。我真的不明白这里发生了什么。我尝试使用传递给接收者的上下文,但我做不到。
【问题讨论】:
【参考方案1】:你不能,也不应该。当 BroadcastReceiver 运行时,您无法保证 Activity 正在运行。如果您需要这样做,您的应用程序的架构就会出错。唯一可以的情况是,如果 BroadcastReceiver 已在 Activity 中注册,并且在这种有限的情况下,您可以将 BR 设为 Activity 的内部类(在这种情况下,它可以访问 Activity 的任何变量)或者可以通过当您通过其构造函数实例化它时的控件。但是任何一种方式都是危险的,因为如果你不小心取消注册,任何一种方式都可能导致它在活动完成后触发。
在任何情况下都不要将视图设为静态变量。不仅会出错(一次不必只有 1 个 Activity 实例),而且会导致整个 Activity 和所有关联变量的内存泄漏。
【讨论】:
0 是的,正如我在问题中提到的那样,我不想将它用作静态。所以 ; 1-)它的正确方法是什么? 2-) 有一个上下文传递给 BroadCastReceiver 。所以我认为该上下文属于 MainActivity ,不是吗?如果是这样,我们可以使用该上下文获取 TextWiev 控件的文本吗? 传递给广播接收器的上下文只是一个上下文。它不必是任何特定的上下文。很可能是它的应用程序上下文,但不要依赖于此。就像我说的 - 你可以做到这一点的唯一方法是如果接收者在活动中注册,然后你需要在构造函数中传递它。如果它是一个清单注册的接收者或注册在一个服务中,你根本不能。【参考方案2】:通过在 BroadcastReceiver 中使用此代码,我可以得到我想要的结果;
TextView currentCharacterName = ((Activity)context).FindViewById<TextView>(Resource.Id.textView1);
我在 mainactivity 中创建了 Broadcastreceiver 并在 mainactivity 中注销它,以防 onPause 或其他与活动停用相关的状态。 我不认为这是最安全和最好的方法,但至少它会更改活动中文本视图的文本,而不会出现任何异常或错误。 最好的问候。
【讨论】:
如果您在MainActivity
中创建BroadcastReceiver
,那么您可以在创建BroadcastReceiver
时传递对MainActivity
的引用(在构造函数中)。然后你可以在参考上调用FindViewById()
。
我在 MainActivity 内外都创建了 Broadcastreceiver ,它们都可以按需要工作。但是,一个问题出现在我面前,那个 Context 是从哪里来的 onReceive?显然,上下文属于我的 Mainactivity,但为什么呢?既然事件广播器不是我的 MainActivity ,为什么那个上下文属于我的 Mainactivity ? "_receiver = new BluetoothDeviceReceiver();"在创建 BluetoothDeviceReceiver 实例或注册期间,mainActiviy 的上下文是否传递给该实例?因为我没有手动传递任何引用。以上是关于如何从广播接收器访问 Activity 的任何控件。不使用“静态”的主要内容,如果未能解决你的问题,请参考以下文章