[英]Using Service as singleton in Android
Is it a bad practice to create a Service
that works as a singleton? 创建一个单独的Service
是不好的做法? I mean a Service
that is never stopped and that contains some private data that some other engines and Activities
would use, so the Service
could have something like: 我的意思是一个永不停止的Service
,它包含一些其他引擎和Activities
将使用的私有数据,因此Service
可能具有以下内容:
public class CustomService extends Service {
private List<Profile> mProfiles;
private static CustomService instance;
public static CustomService getInstance() {
if(instance == null) {
instance = new CustomService();
}
return instance;
}
public List<Profile> getProfiles() {
return mProfiles;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
...
}
...
}
The reason of doing a Service
instead of just a singleton is that it must work independently of the application, as when it starts it connects a websocket that should never be closed and do not depend on the application. 执行Service
而不仅仅是单例的原因是它必须独立于应用程序工作,因为它在启动时连接一个永远不应该关闭且不依赖于应用程序的websocket。 What would you suggest me to do? 你建议我做什么? Is there a better way to re-use the Service
in order to have some data (for instance the mProfiles
array) available from other engines and Activities
? 有没有更好的方法来重新使用Service
,以便从其他引擎和Activities
获得一些数据(例如mProfiles
数组)?
I've read somewhere that a Service
works as a singleton, but I don't know how to access the private variables from any other point in application. 我已经读过一个Service
作为单例工作的地方,但我不知道如何从应用程序中的任何其他点访问私有变量。
Is it a bad practice to create a service that works as a singleton? 创建一个单独的服务是不好的做法?
It is redundant and, in the way you suggest, not going to work from the point of view of Android
Service
as application component which is to perform its functionality with respect to 它是多余的,并且,就你所建议的方式而言,从Android
Service
的角度来看,它不会起作用的应用程序组件,它将执行其功能。
Application
lifecycle that, in its turn, affected by Application
生命周期,反过来受其影响 Such an intention of an application component is reached by 通过以下方式达到应用程序组件的这种意图
AndroidManifest.xml
, 它在AndroidManifest.xml
声明, Application
and "attaching" it to ApplicationThread
/ ActivityThread
. 创建(由系统) Application
中的组件实例并将其“附加”到ApplicationThread
/ ActivityThread
。 That said, brings to the fact that application components are tied to the Application
instance hosted by OS process and can't run independently . 也就是说,应用程序组件与OS进程托管的Application
实例绑定, 无法独立运行 。
Regarding your approach , there are two scenarios : 关于您的方法 ,有两种情况 :
1. CustomService
's default constructor is private as per the pattern. 1.根据模式, CustomService
的默认构造函数是私有的。
By calling getInstance()
a single instance of CustomService
is created. 通过调用getInstance()
,可以创建一个CustomService
实例。 The instance is just a Java
object (singleton) that has nothing in common with Android
Service
application component. 该实例只是一个与Android
Service
应用程序组件没有任何共同点的Java
对象(单例)。 The onStart()
, onStartCommand()
etc. methods will never be called by the system. onStart()
, onStartCommand()
等方法永远不会被系统调用。
An attempt to start the "service" (declared in the manifest) with startService(Intent)
will fail with IllegalAccessException: access to constructor not allowed
. 尝试使用startService(Intent)
启动“服务”(在清单中声明startService(Intent)
将失败并出现IllegalAccessException: access to constructor not allowed
。
2. CustomService
's default constructor is public (as per the code posted). 2. CustomService
的默认构造函数是public (根据发布的代码)。
If the service is declared in AndroidManifest
and the default constructor is empty, startService()
won't fail, however getInstance()
will create another instance of CustomService
that won't be treated as Android
Service
application component. 如果在AndroidManifest
声明服务并且默认构造函数为空,则startService()
不会失败,但是getInstance()
将创建另一个不会被视为Android
Service
应用程序组件的CustomService
实例。
This isn't a singleton. 这不是单身人士。
What would you suggest me to do? 你建议我做什么? Is there a better way to re-use the service in order to have some data (for instance the mProfiles array) available from other engines and activities? 是否有更好的方法来重用服务,以便从其他引擎和活动中获得一些数据(例如mProfiles数组)?
Use Service
as per the documentation and pick the kind of communication you need: 根据文档使用Service
并选择您需要的通信类型:
Activity
-->
Service
) - use a started Service
and handle each Intent
(with your data attached to it, like mProfiles
in case Profile
class implements Parcelable
) in onStartCommand()
; 单向通信( Activity
-->
Service
) -使用开始Service
和处理每个Intent
(与连接到它的数据,如mProfiles
万一Profile
类实现Parcelable
)在onStartCommand()
; Activity
<->
Service
) - use a bound Service
and communicate via IBinder
. 双向通信( Activity
<->
Service
) - 使用绑定Service
并通过IBinder
通信。 Finally, Service
in Android
is a singleton. 最后, Android
中的Service
是一个单身人士。 There is only one instance of each service in the system. 系统中每个服务只有一个实例。 It starts on demand and handles all pending Intent
s / bound clients. 它按需启动并处理所有挂起的Intent
/绑定客户端。 Once it's done or explicitly stopped, it will be destroyed. 一旦完成或明确停止,它将被销毁。
Its bad practice to create a service as a singleton.You can start your service sticky and you can retrieve your service by its name and check if its working or not with the following code from inside an activity. 将服务作为单例创建的不良做法。您可以开始粘贴服务,并且可以通过其名称检索服务,并使用活动内部的以下代码检查其是否正常工作。
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
If (and I haven't found documentation to support this but assume it's the case) the Service is instanciated only once by the Android framework, then you could initialize instance
inside Service.onCreate
. 如果(并且我没有找到支持此文档的文档但假设是这种情况)服务仅由Android框架实例化一次,那么您可以初始化Service.onCreate
instance
。 The only drawback being that you don't have a guarantee when this will be called. 唯一的缺点是,当你被调用时,你没有保证。 Ie, if you call startService inside Application.onCreate
, you'll most likely have to wait a bit before your service is actually instanciated. 即,如果你在Application.onCreate
调用startService,你很可能需要等待一段时间才能真正实现服务。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.