如果片段可见,则从 Service 或 BroadcastReceiver 更新片段 UI
Update Fragment UI from Service or BroadcastReceiver if Fragment is visible
TL;DR
当 运行 服务在屏幕上可见时,我需要更新片段的 UI(toggleButton)。
背景
我在片段(名为 homeFragment)上有一个 toggleButton
。它显示 Stop 文本 if(toggleButton.isChecked)
,否则显示 Start 文本。
toggleButton
启动和停止服务。
现在,有两种方法可以停止此服务。一种是再次点击 toggleButton
(这会停止服务),另一种是通过服务本身。
启动此服务后,toggleButton
显示 'Stop' 文本。
此服务创建粘性通知并在之后调用 this.stopSelf
。
此通知有一个关闭此通知的按钮。
此选项调用 BroadcastReceiver
到 stop/cancel 通知。
Problem/Requirement
现在,当通过通知按钮关闭服务时,如果应用程序可见或在前台,我想在 Fragment 上触发 toggleButton
以显示 Start再次发短信。
如果 appActivity 在 background/paused/closed 中,我不需要处理这个(我通过检查 onCreate()
中的 sharedPrefs
来处理)
我试过了:
使用布尔 SharedPref 键(比如 isServiceRunning
)跟踪服务状态。在 onCreate()
中,我保存了一个 true
布尔值。在 onDestoy()
中,我保存了一个 false
布尔值。
然后,我将 onSharedPreferencesChangeListener
注册到 sharedPrefs(inside fragment)
,它检查 isServiceRunning
的 sharedPrefkey 是否已更改。
如果是,它会调用 toggleButton.setChecked(false);
这种方法很少奏效。有时有效,有时什么也没有。
用了一个LocalBroadcastReceiver
,但是有很多错误。比如,can't Instantiate Receiver: no empty method
。我试图解决,
但发现这需要大量工作。而且,除了在另一个 class 中访问片段视图只是一团糟,因为你必须给他们片段的 layout
任何时候都可以是 null
。给这个接收器 class 一个来自 onViewCreated()
的 View
元素是困难的。我试着给 layout
+ findViewById
充气来做到这一点,
但没有 success/error.
这个方法没用过,我觉得效率不高
到处使用static
变量。所以,我制作了一个全局 View
元素(比如 activeLayout
)。
它是 private
和 static
,因此 static
方法(切换 toggleButton
的状态)可以访问片段的布局。
activeLayout
从 onViewCreated()
方法中分配了一个布局。
现在,如果我从 stopNotificationReceiver
调用此 static
方法,它会起作用(我只检查了两次)。但是,显示了一个新警告:
Warning: Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)
所以,我无法将 activeLayout
作为 static
变量,这打破了整个想法。
如果我做错了,请给我一个替代方案。或者纠正我如何做到这一点。
使用广播接收器并在您的片段中注册它
您可以在您的服务中使用以下代码调用广播接收器
Intent intent = new Intent();
intent.putExtra("extra", cappello);
intent.setAction("com.my.app");
sendBroadcast(intent);
在你的 Fragment 中实现一个 BroadcastReceiver :
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
}
}
并在Fragment的onResume()中注册:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.my.app");
receiver = new MyBroadcastReceiver();
registerReceiver(receiver, intentFilter);
TL;DR
当 运行 服务在屏幕上可见时,我需要更新片段的 UI(toggleButton)。
背景
我在片段(名为 homeFragment)上有一个 toggleButton
。它显示 Stop 文本 if(toggleButton.isChecked)
,否则显示 Start 文本。
toggleButton
启动和停止服务。
现在,有两种方法可以停止此服务。一种是再次点击 toggleButton
(这会停止服务),另一种是通过服务本身。
启动此服务后,toggleButton
显示 'Stop' 文本。
此服务创建粘性通知并在之后调用 this.stopSelf
。
此通知有一个关闭此通知的按钮。
此选项调用 BroadcastReceiver
到 stop/cancel 通知。
Problem/Requirement
现在,当通过通知按钮关闭服务时,如果应用程序可见或在前台,我想在 Fragment 上触发 toggleButton
以显示 Start再次发短信。
如果 appActivity 在 background/paused/closed 中,我不需要处理这个(我通过检查 onCreate()
中的 sharedPrefs
来处理)
我试过了:
使用布尔 SharedPref 键(比如
isServiceRunning
)跟踪服务状态。在onCreate()
中,我保存了一个true
布尔值。在onDestoy()
中,我保存了一个false
布尔值。 然后,我将onSharedPreferencesChangeListener
注册到sharedPrefs(inside fragment)
,它检查isServiceRunning
的 sharedPrefkey 是否已更改。 如果是,它会调用toggleButton.setChecked(false);
这种方法很少奏效。有时有效,有时什么也没有。
用了一个
LocalBroadcastReceiver
,但是有很多错误。比如,can't Instantiate Receiver: no empty method
。我试图解决, 但发现这需要大量工作。而且,除了在另一个 class 中访问片段视图只是一团糟,因为你必须给他们片段的layout
任何时候都可以是null
。给这个接收器 class 一个来自onViewCreated()
的View
元素是困难的。我试着给layout
+findViewById
充气来做到这一点, 但没有 success/error.这个方法没用过,我觉得效率不高
到处使用
static
变量。所以,我制作了一个全局View
元素(比如activeLayout
)。 它是private
和static
,因此static
方法(切换toggleButton
的状态)可以访问片段的布局。activeLayout
从onViewCreated()
方法中分配了一个布局。现在,如果我从
stopNotificationReceiver
调用此static
方法,它会起作用(我只检查了两次)。但是,显示了一个新警告:Warning: Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)
所以,我无法将
activeLayout
作为static
变量,这打破了整个想法。
如果我做错了,请给我一个替代方案。或者纠正我如何做到这一点。
使用广播接收器并在您的片段中注册它
您可以在您的服务中使用以下代码调用广播接收器
Intent intent = new Intent();
intent.putExtra("extra", cappello);
intent.setAction("com.my.app");
sendBroadcast(intent);
在你的 Fragment 中实现一个 BroadcastReceiver :
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
}
}
并在Fragment的onResume()中注册:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.my.app");
receiver = new MyBroadcastReceiver();
registerReceiver(receiver, intentFilter);