Android中的作业管理器

Android中的作业管理器,android,android-service,job-scheduling,wakelock,robospice,Android,Android Service,Job Scheduling,Wakelock,Robospice,我的任务是在Android应用程序中运行几个不同的作业。每项工作都是长期运行的,并且消耗了大量的网络、数据库和文件系统。每个作业都可以由用户手动运行或由AlarmManager安排。每个作业都要一直运行到最后,这一点非常重要,因此在用户离开应用程序后,甚至在用户根本没有打开应用程序时,作业都需要继续运行。作业具有如下某些ID属性: class Job { int id; } 我需要这个假设的JobManager来接收作业并按ID对其进行排序。如果ID=1的作业已在运行,则JobMana

我的任务是在Android应用程序中运行几个不同的作业。每项工作都是长期运行的,并且消耗了大量的网络、数据库和文件系统。每个作业都可以由用户手动运行或由AlarmManager安排。每个作业都要一直运行到最后,这一点非常重要,因此在用户离开应用程序后,甚至在用户根本没有打开应用程序时,作业都需要继续运行。作业具有如下某些ID属性:

class Job {
    int id;
}
我需要这个假设的JobManager来接收作业并按ID对其进行排序。如果ID=1的作业已在运行,则JobManager应跳过ID=1的所有后续作业,直到此作业完成。但是,如果提交了id为2的作业,那么它将被接受,并且可以与第一个作业并行运行

作业还应该保持唤醒锁定直到完成,就像在Commonware的WakefulIntentService中完成一样

我有几个想法如何实现这一点,但都有其缺点:

  • 服务类的子类,它总是在后台运行,并且在由于某种原因被终止时自动重新启动。缺点:即使不运行任何东西,它也会消耗资源,它在UI线程上运行,因此我们必须像往常一样管理一些可能被系统终止的线程,每个客户端都必须启动服务,并且没有人知道何时停止服务
  • 来自Commonware的WakefulIntentService。缺点:因为它是IntentService,所以只能按顺序运行,所以无法检查现有正在运行的作业
  • 数据库中每个作业的布尔“运行”标志。每次我们要运行作业时都要检查它。缺点:对数据库的请求太多,难以正确实现,有时两个相等的作业仍然可以并行运行,不确定在出现意外错误时标志是否保持“true”
  • 为此目的而设计的现有图书馆。到目前为止,除了CWAC Wakeful,我发现:

    • 机器人世界:
    • Android作业队列:
    但我仍然不知道,如何使用这些库来运行一个集中的服务,即接受来自任何其他活动、服务、广播接收器、AlarmManager等的作业,按ID排序并并行运行

  • 请告诉我在这种情况下可以使用什么解决方案


    更新:请参见下面我自己的解决方案。我不确定它是否在所有可能的情况下都有效。如果您知道这可能会出现任何问题,请发表评论。

    这似乎适合棒棒糖上的新API,那么您必须在其周围制作一个包装器,以实现sdk实现缺少的所有功能


    如果您需要在Lollipop下面的版本上实现此功能,则有一个库。

    这似乎适合Lollipop上的新API,然后您必须在其周围制作一个包装器,以实现sdk实现缺少的所有功能


    如果您需要在Lollipop下面的版本上实现此功能,则有一个库。

    这似乎适合Lollipop上的新API,然后您必须在其周围制作一个包装器,以实现sdk实现缺少的所有功能


    如果您需要在Lollipop下面的版本上实现此功能,则有一个库。

    这似乎适合Lollipop上的新API,然后您必须在其周围制作一个包装器,以实现sdk实现缺少的所有功能


    如果您需要在Lollipop下面的版本上实现此功能,那么有一个库。

    如果有人面临相同的问题,下面是我提出的解决方案。我使用了Robospice库,因为它是在服务上运行某些作业并将结果同步回活动的最健壮的方法。由于我没有找到任何方法将这个库用于WakeLocks,所以我扩展了2个类:SpiceManager和SpiceRequest。新类WakefulSpiceManager和WakefulSpiceRequest实际上借用了Commonware关于WakeLocks的思想,实现非常相似

    唤醒管理器:

    public class WakefulSpiceManager extends SpiceManager {
        private static final String NAME = "WakefulSpiceManager";
        private static volatile PowerManager.WakeLock wakeLock;
        private Context context;
    
        public WakefulSpiceManager(Context context, Class<? extends SpiceService> spiceServiceClass) {
            super(spiceServiceClass);
            this.context = context;
            start(context);
        }
    
        private static synchronized PowerManager.WakeLock getLock(Context context) {
            if (wakeLock == null) {
                PowerManager mgr = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    
                wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NAME);
                wakeLock.setReferenceCounted(true);
            }
    
            return wakeLock;
        }
    
        public <T> void execute(WakefulSpiceRequest<T> request, RequestListener<T> requestListener) {
            PowerManager.WakeLock lock = getLock(context);
            lock.acquire();
            request.setLock(lock);
    
            // explicitly avoid caching
            super.execute(new CachedSpiceRequest<T>(request, null, ALWAYS_EXPIRED), requestListener);
        }
    }
    
        WakefulSpiceManager manager = new WakefulSpiceManager(context, MyService.class);
        manager.execute(new WakefulSpiceRequest<MyResult>(MyResult.class) {
            @Override
            public MyResult execute() throws Exception {
                return ...
            }
        }, new RequestListener<MyResult>() {
            @Override
            public void onRequestFailure(SpiceException e) {
                ...
            }
    
            @Override
            public void onRequestSuccess(MyResult result) {
                ...
            }
        });
    
    公共类WakefulSpiceManager扩展了SpiceManager{
    私有静态最终字符串NAME=“WakefulSpiceManager”;
    私有静态易失性PowerManager.WakeLock WakeLock;
    私人语境;
    
    公共服务经理(Context Context,Class如果有人面临同样的问题,下面是我提出的解决方案。我使用Robospice lib,因为它是在服务上运行某些作业并将结果同步回活动的最健壮的方法。由于我没有找到任何方法将此lib与WakeLocks一起使用,因此我扩展了两个类:SpiceManager和SpiceRequest。新的类WakefulSpiceManager和WakefulSpiceRequest实际上借用了Commonware关于WakeLocks的思想,实现非常相似

    唤醒管理器:

    public class WakefulSpiceManager extends SpiceManager {
        private static final String NAME = "WakefulSpiceManager";
        private static volatile PowerManager.WakeLock wakeLock;
        private Context context;
    
        public WakefulSpiceManager(Context context, Class<? extends SpiceService> spiceServiceClass) {
            super(spiceServiceClass);
            this.context = context;
            start(context);
        }
    
        private static synchronized PowerManager.WakeLock getLock(Context context) {
            if (wakeLock == null) {
                PowerManager mgr = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    
                wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NAME);
                wakeLock.setReferenceCounted(true);
            }
    
            return wakeLock;
        }
    
        public <T> void execute(WakefulSpiceRequest<T> request, RequestListener<T> requestListener) {
            PowerManager.WakeLock lock = getLock(context);
            lock.acquire();
            request.setLock(lock);
    
            // explicitly avoid caching
            super.execute(new CachedSpiceRequest<T>(request, null, ALWAYS_EXPIRED), requestListener);
        }
    }
    
        WakefulSpiceManager manager = new WakefulSpiceManager(context, MyService.class);
        manager.execute(new WakefulSpiceRequest<MyResult>(MyResult.class) {
            @Override
            public MyResult execute() throws Exception {
                return ...
            }
        }, new RequestListener<MyResult>() {
            @Override
            public void onRequestFailure(SpiceException e) {
                ...
            }
    
            @Override
            public void onRequestSuccess(MyResult result) {
                ...
            }
        });
    
    公共类WakefulSpiceManager扩展了SpiceManager{
    私有静态最终字符串NAME=“WakefulSpiceManager”;
    私有静态易失性PowerManager.WakeLock WakeLock;
    私人语境;
    
    公共服务经理(Context Context,Class如果有人面临同样的问题,下面是我提出的解决方案。我使用Robospice lib,因为它是在服务上运行某些作业并将结果同步回活动的最健壮的方法。由于我没有找到任何方法将此lib与WakeLocks一起使用,因此我扩展了两个类:SpiceManager和SpiceRequest。新的类WakefulSpiceManager和WakefulSpiceRequest实际上借用了Commonware关于WakeLocks的思想,实现非常相似

    唤醒管理器:

    public class WakefulSpiceManager extends SpiceManager {
        private static final String NAME = "WakefulSpiceManager";
        private static volatile PowerManager.WakeLock wakeLock;
        private Context context;
    
        public WakefulSpiceManager(Context context, Class<? extends SpiceService> spiceServiceClass) {
            super(spiceServiceClass);
            this.context = context;
            start(context);
        }
    
        private static synchronized PowerManager.WakeLock getLock(Context context) {
            if (wakeLock == null) {
                PowerManager mgr = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    
                wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NAME);
                wakeLock.setReferenceCounted(true);
            }
    
            return wakeLock;
        }
    
        public <T> void execute(WakefulSpiceRequest<T> request, RequestListener<T> requestListener) {
            PowerManager.WakeLock lock = getLock(context);
            lock.acquire();
            request.setLock(lock);
    
            // explicitly avoid caching
            super.execute(new CachedSpiceRequest<T>(request, null, ALWAYS_EXPIRED), requestListener);
        }
    }
    
        WakefulSpiceManager manager = new WakefulSpiceManager(context, MyService.class);
        manager.execute(new WakefulSpiceRequest<MyResult>(MyResult.class) {
            @Override
            public MyResult execute() throws Exception {
                return ...
            }
        }, new RequestListener<MyResult>() {
            @Override
            public void onRequestFailure(SpiceException e) {
                ...
            }
    
            @Override
            public void onRequestSuccess(MyResult result) {
                ...
            }
        });
    
    公共类WakefulSpiceManager扩展了SpiceManager{
    私有静态最终字符串NAME=“WakefulSpiceManager”;
    私有静态易失性PowerManager.WakeLock WakeLock;
    私人语境;
    
    public WakefulSpiceManager(上下文,类如果有人面临同样的问题,下面是我提出的解决方案。我使用Robospice lib,因为它是在服务上运行某些作业并将结果同步回活动的最可靠的方法。因为我没有找到任何方法