Java 如果片段可见,则从服务或BroadcastReceiver更新片段UI
TL;DR 我需要更新一个片段的UI(toggleButton),当它在运行服务的屏幕上可见时 背景 我在片段(名为homeFragment)上有一个Java 如果片段可见,则从服务或BroadcastReceiver更新片段UI,java,android,android-fragments,broadcastreceiver,android-service,Java,Android,Android Fragments,Broadcastreceiver,Android Service,TL;DR 我需要更新一个片段的UI(toggleButton),当它在运行服务的屏幕上可见时 背景 我在片段(名为homeFragment)上有一个切换按钮。如果(toggleButton.isChecked),则显示停止文本,否则显示开始文本。 此切换按钮启动和停止服务 现在,有两种方法可以停止此服务。一个是再次点击toggleButton(停止服务),另一个是通过服务本身 启动此服务时,toggleButton显示“停止”文本。 此服务创建一个粘性通知,然后调用This.stopSelf。
切换按钮
。如果(toggleButton.isChecked),则显示停止文本,否则显示开始文本。
此切换按钮启动和停止服务
现在,有两种方法可以停止此服务。一个是再次点击toggleButton
(停止服务),另一个是通过服务本身
启动此服务时,toggleButton
显示“停止”文本。
此服务创建一个粘性通知,然后调用This.stopSelf
。
此通知具有关闭此通知的按钮。
此选项调用BroadcastReceiver
停止/取消通知
问题/要求
现在,当服务通过通知按钮关闭时,如果应用程序可见或在前台,我想触发片段上的toggleButton
,再次显示开始文本。
如果appActivity处于后台/暂停/关闭状态,我不需要处理此问题(我通过在onCreate()
中检查sharedPrefs
来处理此问题)
我试过:
使用一个布尔SharedPref键(比如isServiceRunning
),它跟踪服务状态。在onCreate()
中,我保存了一个true
布尔值。在onDestoy()
中,我保存了一个false
布尔值。
然后,我在SharedPreferencesChangeListener上注册一个到sharedPrefs(内部片段)
,它检查isServiceRunning
的sharedPrefkey是否更改。
如果是,则调用toggleButton.setChecked(false)代码>
这种方法很少奏效。有时有效,有时什么也没发生
使用LocalBroadcastReceiver
,但它有许多错误。比如,无法实例化Receiver:no empty方法
。我试图解决,
但我发现这需要很多工作。此外,在另一个类中访问片段视图也是一团糟,因为您必须为它们提供片段的布局
它可以在任何时间null
。很难从onViewCreated()
中为该接收器类指定一个视图元素。我尝试通过膨胀布局
+findViewById
来完成此操作,
但没有成功/错误
这种方法从来都不管用,我认为它效率不高
到处使用静态
变量。因此,我创建了一个全局视图
元素(比如activeLayout
)。
它是私有的
和静态的
,因此静态的
方法(切换切换按钮
的状态)可以访问片段的布局。
activeLayout
从onViewCreated()
方法分配一个布局
现在,如果我从我的stopNotificationReceiver
调用这个static
方法,它就会工作(我只检查了两次)。但是,新的警告显示:
警告:不要将Android上下文类放在静态字段中;这是内存泄漏(也会中断即时运行)
因此,我不能将activeLayout
作为static
变量,这打破了整个想法
如果我做错了,请给我一个选择。或者告诉我怎么做。使用广播接收器并将其注册到片段中
您可以在您的服务中使用以下代码调用广播接收器
Intent intent = new Intent();
intent.putExtra("extra", cappello);
intent.setAction("com.my.app");
sendBroadcast(intent);
在片段中实现一个广播接收器:
private class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
String state = extras.getString("extra");
updateView(state);// update your textView in the main layout
}
}
并将其注册到片段的onResume()中:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.my.app");
receiver = new MyBroadcastReceiver();
registerReceiver(receiver, intentFilter);
使用广播接收器并将其注册到片段中
您可以在您的服务中使用以下代码调用广播接收器
Intent intent = new Intent();
intent.putExtra("extra", cappello);
intent.setAction("com.my.app");
sendBroadcast(intent);
在片段中实现一个广播接收器:
private class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
String state = extras.getString("extra");
updateView(state);// update your textView in the main layout
}
}
并将其注册到片段的onResume()中:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.my.app");
receiver = new MyBroadcastReceiver();
registerReceiver(receiver, intentFilter);
在onPause()
中注销如果片段不可见,则不调用broadcastReceiver?或者它被触发,但用户界面的更新被忽略?在onPause()
中注销如果片段不可见,则不调用broadcastReceiver?或者它被触发了,但是用户界面的更新被忽略了?