在我的应用程序中,我有一个Service
,它负责管理与外部设备的蓝牙连接。此Service
类定期轮询外部蓝牙设备的数据,并将最新数据添加到缓存(或可能是SD卡)内存中的日志中。
在我拥有的各种Activity
类中,有一个特定的Activity
代表主UI。它负责以图形形式显示基于缓存文件数据的记录数据。我们称之为Activity
Dashboard
。用户可以在该图表上来回滚动,以查看自应用程序启动以来在缓存中收集和记录的数据。
出于这个问题的目的,有两种操作模式需要考虑。用户可以选择“登录到SD卡”选项,即使所有Activity
类都被杀死,应用程序也必须继续轮询并记录到SD卡(例如,用户已经返回到发射器)。在这种情况下,我的Service
使用.startService()
启动并继续运行,并且只有在用户再次调用应用程序并禁用SD卡日志记录时才会停止。另一种模式是用户没有选择“登录到SD卡”,在这种情况下,Service
仍在管理蓝牙连接,轮询和记录到高速缓冲存储器,以便在视觉上显示数据。图表,但只需要在使用Dashboard
Activity
时执行此操作。
我目前所拥有的是Dashboard
Activity
最初使用Service
绑定到bindService()
,并在unbindService()
内对onPause()
进行相应的调用Service
方法(否则我会泄漏Service
)。
问题是Activity
需要保持蓝牙连接并在方向更改期间或用户通过顶部调用另一个startService()
时继续记录(例如检查电子邮件)。现在,如果用户选择了“登录到SD卡”,导致拨打Activity
,那么当然没有问题。问题当然是如何区分被销毁的Service
然后由于方向(或其他一些配置)的变化而再次创建,并且因为用户返回到启动器而被销毁。在前一种情况下,我不希望Service
数据记录被中断。在后一种情况下,我希望startService()
停止,如果用户没有选择“登录到SD卡”。
目前我能想到的最佳解决方案是使用Dashboard
始终启动服务,以便在Service
时继续运行已被摧毁。我会做的是在Service
内实施超时,Dashboard
将自行停止,除非连续SD卡日志已启用,或 onCreate
在{5}内再次Service
d(比如说)并重新绑定到{{1}}。这似乎有点粗糙,我不禁想到这一定是一个常见的设计问题,有一个我忽略的更好的解决方案。
答案 0 :(得分:6)
选项1:如果您希望在主要活动结束时立即销毁服务。
在绑定之前手动启动时,服务不会被销毁:
protected void onStart() {
Intent intent = new Intent(getApplicationContext(), MServcie.class);
startService(intent);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
仅在您的活动完成时停止服务!
protected void onStop() {
if (service != null) {
unbindService(connection);
service = null;
if (isFinishing()) {
stopService(new Intent(getApplicationContext(), MyServcie.class));
}
}
}
选项2:如果您希望操作系统决定何时停止服务。
protected void onStart() {
Intent intent = new Intent(this, MServcie.class);
getApplicationContext().bindService(intent, this, Context.BIND_AUTO_CREATE);
}
答案 1 :(得分:4)
您可以使用的一种方法是在isFinishing()
解除绑定之前检查活动onPause()
。如果它正在完成,您可以将解除绑定推迟到onDestroy()
方法。但是,在调用onDestroy()
之前,您可以使用onRetainNonConfigurationInstance()
方法保留ServiceConnection。如果你确实执行了持久性,那么根本不会在你的unBind()
内部实际调用onDestroy()
,只需让你的Activity的新实例进行解除绑定。
话虽如此,根据您的应用程序,您可能会发现启动/停止服务更容易。
答案 2 :(得分:3)
正如您可能已经知道的那样,服务实际上是为了与活动建立单独的生命周期。因此,您可以考虑不将纯服务用于纯粹的监控方案。在背景情况下,您只需要与活动分开的生命周期,但在纯粹的监控情况下则不需要。
您真正想要的是您的日志记录与应用程序的生命周期相关联,并且您可以通过启动/停止活动或您的活动来控制应用程序的生命周期服务。如果您在可从Application对象访问的单独线程中进行轮询,则您的Activities根本不需要与Service绑定,而只需与此日志记录线程进行通信。当您确实需要后台日志记录时,您可以启动/停止服务,该服务还可以与日志记录线程进行通信,以便在停止时正常清理,正确重新启动等等。
答案 3 :(得分:3)
您应该使用isChangingConfigurations()
,而不是isFinishing()
:后者是false
,如果活动失去了可见性,配置发生变化,那么您无法区分。< / p>