在 Android 中将服务用作单例

Using Service as singleton in Android

创建一个作为单例工作的 Service 是一种不好的做法吗?我的意思是 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) {
         ...
     }
     ...
}

做一个 Service 而不是单例的原因是它必须独立于应用程序工作,因为当它启动时它连接一个永远不应该关闭并且不依赖于应用程序的 websocket .你会建议我做什么?有没有更好的方法来重新使用 Service 以便从其他引擎和 Activities?

获得一些数据(例如 mProfiles 数组)

我在某处读到 Service 作为单例工作,但我不知道如何从应用程序的任何其他点访问私有变量。

Is it a bad practice to create a service that works as a singleton?

它是多余的,并且按照您建议的方式,从 Android Service 的角度来看,它不会工作,因为应用程序组件将执行其关于 [= 的功能59=]

  • Application 生命周期,反过来又受
  • 影响
  • 系统事件。

应用程序组件的这种意图是通过

达到的
  • 它在 AndroidManifest.xml
  • 中的声明
  • 触发它(启动/绑定/注册)和
  • (由系统)在 Application 和 "attaching" 中创建组件实例到 ApplicationThread/ActivityThread

也就是说,应用程序组件绑定到 OS 进程托管的 Application 实例并且 不能 运行 独立.


关于你的方法,有两种情况

1. CustomService 的默认 构造函数是私有的 图案。

通过调用 getInstance() 创建了 CustomService 的单个实例。该实例只是一个 Java 对象(单例),与 Android Service 应用程序组件没有任何共同之处。 onStart()onStartCommand()等方法永远不会被系统调用。

尝试使用 startService(Intent) 启动 "service"(在清单中声明)将失败并显示 IllegalAccessException: access to constructor not allowed

2. CustomService的默认构造函数是public(根据发布的代码)。

如果服务在 AndroidManifest 中声明并且默认构造函数为空,startService() 不会失败,但是 getInstance() 将创建另一个 CustomService 的实例不会被视为 Android Service 应用程序组件。

这不是单例。


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?

根据 the documentation 使用 Service 并选择您需要的通信类型:

  • One-way通讯(Activity-->Service)-在onStartCommand();
  • 中使用started Service and handle each Intent (with your data attached to it, like mProfiles in case Profile class implements Parcelable)
  • Two-way 通讯 (Activity <-> Service) - 使用 bound Service 并通过 IBinder.
  • 通讯

最后,Android中的Service是一个单例。系统中每个服务只有一个实例。它按需启动并处理所有未决的 Intents / 绑定客户端。一旦完成或明确停止,它将被销毁。

将服务创建为 singleton.You 的错误做法可能会使您的服务变得粘滞,您可以通过其名称检索您的服务,并使用 [=14] 中的以下代码检查其是否正常工作=].

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;
}

如果(我还没有找到支持这一点的文档,但假设是这种情况)服务仅由 Android 框架实例化一次,那么您可以在 Service.onCreate。唯一的缺点是您无法保证何时调用它。也就是说,如果您在 Application.onCreate 中调用 startService,您很可能需要稍等片刻才能实际实例化您的服务。