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

时间:2016-01-26 21:26:59

标签: android design-patterns singleton android-service android-lifecycle

创建一个作为单身人士的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以获得其他引擎和mProfiles提供的某些数据(例如Activities数组)?

我已经在某个地方读过Service作为单身人士的工作,但我不知道如何从应用程序的任何其他位置访问私有变量。

3 个答案:

答案 0 :(得分:13)

  

创建一个单独的服务是不好的做法吗?

这是多余的,并且,就您所建议的方式而言,从Android Service作为应用程序组件的角度来看,它不会起作用,而

是执行其功能的
  • Application生命周期,反过来受
  • 的影响
  • 系统事件。

达到了应用程序组件的这种意图
  • AndroidManifest.xml
  • 中的声明
  • 触发它(开始/绑定/注册)和
  • 创建(由系统)Application内的组件实例和&#34;附加&#34;它是ApplicationThread / ActivityThread

这就是说,应用程序组件与操作系统进程托管的Application实例绑定,无法独立运行

关于您的方法,有两个方案

1。 CustomService 的默认构造函数是私有,符合模式。

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

尝试启动&#34;服务&#34; (使用startService(Intent)在清单中声明)将失败并显示IllegalAccessException: access to constructor not allowed

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

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

这不是一个单身人士。

  

你建议我做什么?有没有更好的方法来重新使用该服务,以便从其他引擎和活动中获得一些数据(例如mProfiles数组)?

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

  • 单向沟通(Activity --> Service) - 使用started Service并处理每个Intent(附上您的数据,例如{ {1}}如果mProfiles类在Profile中实现Parcelable);
  • 双向沟通(onStartCommand() Activity <->) - 使用bound Service并通过Service进行沟通。

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

答案 1 :(得分:1)

将服务创建为单例的不良做法。您可以启动服务粘性,您可以通过其名称检索服务,并使用活动内部的以下代码检查其是否正常工作。

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

答案 2 :(得分:0)

如果(我还没有找到支持此文档的文档但假设是这种情况),Android框架只会对服务进行一次实例化,那么您可以在instance内初始化Service.onCreate。唯一的缺点是,当你被调用时,你没有保证。也就是说,如果你在Application.onCreate内调用startService,你很可能需要等待一段时间才能真正实现服务。