简体   繁体   English

在Android中将服务用作单身人士

[英]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生命周期,反过来受其影响
  • system events. 系统事件。

Such an intention of an application component is reached by 通过以下方式达到应用程序组件的这种意图

  • its declaration in the AndroidManifest.xml , 它在AndroidManifest.xml声明,
  • triggering it (starting / binding / registering) and 触发它(开始/绑定/注册)和
  • creating (by the system) an instance of the component within 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并选择您需要的通信类型:

  • One-way communication ( 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() ;
  • Two-way communication ( 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM