从服务内部显示 Snackbar
Posted
技术标签:
【中文标题】从服务内部显示 Snackbar【英文标题】:Showing a Snackbar from inside a Service 【发布时间】:2016-04-24 02:45:02 【问题描述】:当从Activity
内部显示SnackBar
时,我有可用的rootView
。但我需要从Service
内部显示SnackBar
,我没有可用的View
。我怎样才能做到这一点?
作为背景故事:一个活动启动一个服务来完成一项任务。 Service
需要根据情况显示SnackBar
。我不想为此绑定到Service
。那么我怎么能做到这一点呢?通常我可以显示Toast
,但我需要用户能够阅读消息并确认。
【问题讨论】:
澄清一下,您是在询问是否能够在用户使用应用程序时或任何时候显示 Snackbar,即使应用程序已关闭? 【参考方案1】:Snackbar
需要 View
才能显示,因此如果您想根据 Service
的状态在您的应用上显示快餐栏,您必须将其绑定到您的 Activity
或广播通过LocalBroadcastManager
发送消息并在您的View
上显示消息。
我认为没有其他方法可以解决它,您必须以某种方式与您的Activity
或Fragment
通信。
Snackbars 不像 Toasts 只需要一个上下文,所以如果你想在你的应用程序之外显示它,我相信你不能使用 android 提供的类。
来自design guidelines:
展示位置
Snackbars 出现在屏幕上大多数元素的上方,它们在 浮动操作按钮的高度。然而,它们在 比对话框、底部工作表和导航抽屉高。
这并不明确,但您可以得出结论,它只会显示在您的应用视图中。因此,再次,您必须以某种方式与您的可见视图进行通信。
广播消息的片段:
发件人(在您的服务上)
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);
接收者(在您的活动中)
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 与您的可见 视图进行通信,因为它以发布者/订阅者的方式工作。您甚至可以利用Sticky events 的概念来确保一旦应用再次可见,Snackbar
就会显示出来。
看看我的this answer 了解如何使用事件总线。
【讨论】:
【参考方案2】:您始终可以通过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)
【讨论】:
感谢您的帮助。 +1。我只能接受一个答案,所以我掷硬币。谢谢。【参考方案3】:如何使用在多个活动中可见的应用程序上下文创建 Snackbar:https://***.com/a/37707741/1185087
【讨论】:
【参考方案4】:使用 SDK 提供的默认 SnackBar
是不可能的,因为它总是需要一个视图。
为了达到您的目的,您可以使用一些模仿 SnackBar 的外部库,例如 this one
【讨论】:
会很感激有人投反对票的原因,除非是通过相互竞争的答案来寻求关注。 :) 这里经常发生这种情况。我讨厌它,它没有建设性。 不,@AndroidMechanic,您必须将视图传递给 SDK 或此库提供的 SnackBar。您将能够找到 2 个构造函数。 #1new SnackBar.Builder(this)
- this
作为活动。 #1 new SnackBar.Builder(getActivity().getApplicationContext(), root)
- root
作为视图根以上是关于从服务内部显示 Snackbar的主要内容,如果未能解决你的问题,请参考以下文章