从服务内部显示 Snackbar
Showing a Snackbar from inside a Service
当从 Activity
中显示 SnackBar
时,我可以使用 rootView
。但是我需要从 Service
中显示 SnackBar
,而我没有可用的 View
。我怎样才能做到这一点?
作为背景故事:activity 启动服务来执行任务。 Service
需要根据情况显示 SnackBar
。我不想为此绑定到 Service
。那么我该如何实现呢?通常我可以显示 Toast
,但我需要用户能够阅读消息并确认。
您可以随时通过 Service
中的 LocalBroadcastManager
发送广播
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent("SERVICE_DID_SOMETHING"));
然后在Activity
中使用BroadcastReceiver
来显示Snackbar
private final ServiceReceiver _serviceReceiver = new ServiceReceiver();
@Override
protected void onResume() {
super.onResume();
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("SERVICE_DID_SOMETHING");
LocalBroadcastManager.getInstance(this).registerReceiver(_serviceReceiver, intentFilter);
}
@Override
protected void onPause() {
super.onPause();
try {
LocalBroadcastManager.getInstance(this).unregisterReceiver(_serviceReceiver);
} catch (Exception ex) {
Log.e(TAG, "Error unregistering ServiceReceiver", ex);
}
}
// region ServiceReceiver
private class ServiceReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: Show your Snackbar here...
}
}
// endregion
如果需要,您可以使用发送的 Intent
传递额外数据,然后在 BroadcastReceiver.onReceive(Context context, Intent intent)
中将其拉出
Snackbar
needs a View
to be displayed, so if you want to show snackbars on your app depending on the state of your Service
you'll have to either bind it to your Activity
or broadcast a message through the LocalBroadcastManager
并在您的 View
上显示消息。
我认为没有其他解决方法,您必须以某种方式与 Activity
或 Fragment
进行通信。
Snackbars 不像 Toasts 那样只需要一个上下文,所以如果你想在你的应用程序之外显示它,我相信你不能使用 class 由 Android.
提供
从 design guidelines 开始:
Placement
Snackbars appear above most elements on screen, and they are equal in
elevation to the floating action button. However, they are lower in
elevation than dialogs, bottom sheets, and navigation drawers.
它并不明确,但您可以得出结论,它只会显示在您的应用视图中。因此,同样,您必须以某种方式与 visible 视图进行通信。
广播消息的片段:
发件人(在您的服务上)
private void doSendBroadcast(String message) {
Intent it = new Intent("EVENT_SNACKBAR");
if (!TextUtils.isEmpty(message))
it.putExtra(EXTRA_RETURN_MESSAGE,message);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(it);
}
接收器(在您的 Activity 上)
private BroadcastReceiver mMessageReceiver = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Other stuff.
mMessageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Do something
}
};
}
@Override
public void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter("EVENT_SNACKBAR"));
}
有关绑定服务的更多信息here。
大约 LocalBroadcastManager
here on this question.
更新: 您还可以使用 EventBus to communicate with your visible view, as it works on a Publisher/Subscriber fashion. You could even make use of the concept of Sticky events 来确保 Snackbar
将在应用程序再次可见时显示。
看看我的 关于如何使用事件总线的文章。
无法使用 SDK 提供的默认值 SnackBar
执行此操作,因为它始终需要一个视图。
为了达到您的目的,您可以使用一些模仿 SnackBar 的外部库,例如 this one
如何使用跨多个活动可见的应用程序上下文创建 Snackbar:
当从 Activity
中显示 SnackBar
时,我可以使用 rootView
。但是我需要从 Service
中显示 SnackBar
,而我没有可用的 View
。我怎样才能做到这一点?
作为背景故事:activity 启动服务来执行任务。 Service
需要根据情况显示 SnackBar
。我不想为此绑定到 Service
。那么我该如何实现呢?通常我可以显示 Toast
,但我需要用户能够阅读消息并确认。
您可以随时通过 Service
LocalBroadcastManager
发送广播
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent("SERVICE_DID_SOMETHING"));
然后在Activity
中使用BroadcastReceiver
来显示Snackbar
private final ServiceReceiver _serviceReceiver = new ServiceReceiver();
@Override
protected void onResume() {
super.onResume();
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("SERVICE_DID_SOMETHING");
LocalBroadcastManager.getInstance(this).registerReceiver(_serviceReceiver, intentFilter);
}
@Override
protected void onPause() {
super.onPause();
try {
LocalBroadcastManager.getInstance(this).unregisterReceiver(_serviceReceiver);
} catch (Exception ex) {
Log.e(TAG, "Error unregistering ServiceReceiver", ex);
}
}
// region ServiceReceiver
private class ServiceReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: Show your Snackbar here...
}
}
// endregion
如果需要,您可以使用发送的 Intent
传递额外数据,然后在 BroadcastReceiver.onReceive(Context context, Intent intent)
Snackbar
needs a View
to be displayed, so if you want to show snackbars on your app depending on the state of your Service
you'll have to either bind it to your Activity
or broadcast a message through the LocalBroadcastManager
并在您的 View
上显示消息。
我认为没有其他解决方法,您必须以某种方式与 Activity
或 Fragment
进行通信。
Snackbars 不像 Toasts 那样只需要一个上下文,所以如果你想在你的应用程序之外显示它,我相信你不能使用 class 由 Android.
提供从 design guidelines 开始:
Placement
Snackbars appear above most elements on screen, and they are equal in elevation to the floating action button. However, they are lower in elevation than dialogs, bottom sheets, and navigation drawers.
它并不明确,但您可以得出结论,它只会显示在您的应用视图中。因此,同样,您必须以某种方式与 visible 视图进行通信。
广播消息的片段:
发件人(在您的服务上)
private void doSendBroadcast(String message) {
Intent it = new Intent("EVENT_SNACKBAR");
if (!TextUtils.isEmpty(message))
it.putExtra(EXTRA_RETURN_MESSAGE,message);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(it);
}
接收器(在您的 Activity 上)
private BroadcastReceiver mMessageReceiver = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Other stuff.
mMessageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Do something
}
};
}
@Override
public void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter("EVENT_SNACKBAR"));
}
有关绑定服务的更多信息here。
大约 LocalBroadcastManager
here on this question.
更新: 您还可以使用 EventBus to communicate with your visible view, as it works on a Publisher/Subscriber fashion. You could even make use of the concept of Sticky events 来确保 Snackbar
将在应用程序再次可见时显示。
看看我的
无法使用 SDK 提供的默认值 SnackBar
执行此操作,因为它始终需要一个视图。
为了达到您的目的,您可以使用一些模仿 SnackBar 的外部库,例如 this one
如何使用跨多个活动可见的应用程序上下文创建 Snackbar: