我有一个Android服务,让我们说“Service.java”
我启动一个实例并将一个唯一的id传递给我启动的每个服务实例(这样我就没有同时运行同一个uid的两个服务):
Intent intent = new Intent(this, Service.class);
intent.putExtra("KEY", uid);
startService(intent);
假设我在“Service.java”中为此uid设置了一个变量:
private String uid;
@Override
public int onStartCommand(Intent intent, int flags, final int startId) {
super.onStartCommand(intent, flags, startId);
if(intent != null) {
Bundle infoBundle = intent.getExtras();
this.uid = infoBundle.getString("KEY");
}
...
}
public String getUid() { return this.uid; }
有没有办法以某种方式检查“Service.java”的实例是否正在使用给定的uid运行并将其杀死?
我有一个键/值对列表,我希望在一天中的特定时间启动此服务的实例,但如果用户“禁用”某个时间段(键/值对),我想要服务停下来。
背景故事:
我有一个应用程序在给定时间之前30分钟启动服务以轮询数据源以进行更改。数据馈送不再可用后,该服务将自行终止。
如果用户“不喜欢/禁用”这个时段(键/值对 - uid),我不希望服务在接下来的30分钟内运行,所以我想在它“不受欢迎”时立即将其杀死/禁止“
我可能会以错误的方式解决这个问题。
无论哪种方式,非常感谢输入,谢谢!
答案 0 :(得分:1)
我更多地将其视为:您的服务需要知道数据模型何时发生变化。在这种情况下,数据模型是“键/值对列表”,每个都具有启用/禁用状态。
假设存储在数据库SharedPreferences
或具有单例缓存的文件中以便快速访问,那么这里有三种选择让服务知道数据模型的变化:
使用事件总线或其他一些侦听器模式,因此如果服务存在,它会发现有关更改并可以采取一些适当的步骤。如果您的服务在单独的进程中运行,则事件总线必须是系统级广播(与LocalBroadcastManager
相反,后者是进程内事件总线)。
使用ContentProvider
在数据模型前面并使用ContentObserver
通知更改(这就像用别克拍苍蝇一样,但是,嘿,这是一个选项)。
更改数据模型时调用startService()
,并使用一些信息(例如,自定义操作字符串)让服务知道这是“检查您的数据模型”事件。这种方法的缺点是,如果服务尚未启动,则启动服务,但可能服务会意识到如果没有任何事情要做,只是立即停止服务。
就个人而言,我会选择#1选项。
但是,要回到您的文字问题,根据需要从服务中提取数据的唯一好方法是使用绑定模式,您的客户端通过bindService()
连接到服务并且服务发布一个Binder
形式的API。这与您当前的方法并不相互排斥。但是,这种方法的缺点类似于上面的#3:如果服务尚未运行,尝试绑定到它的行为将创建服务的实例。
没有什么可以阻止你采取“哦,服务是一个单身,所以我将通过一些static
字段某处跟踪其状态”方法。我甚至偶尔也会为废话应用程序做过这件事,虽然它让我感到不安。它也仅适用于与应用程序其余部分相同的过程中的服务;如果您的服务是在一个单独的过程中,这种方法不起作用。
答案 1 :(得分:0)
根据文件,
请求启动给定的应用程序服务。意图可以 要么包含特定服务的完整类名 启动的实现,或通过操作的抽象定义 和其他领域的服务开始。如果是这项服务 尚未运行,它将被实例化并启动(创建一个 如果需要,它的过程);如果它正在运行,那么它仍然在运行。
但是如果你使用的是startService();
您应该指定何时停止服务中的服务,
并且您应该知道该服务将在主线程上运行(哪个阻塞主线程),除非您在服务中启动新线程,或者使用IntentService,它使用工作线程轮流处理每个Intent ,当它用完时停止运转。
您可以拥有一个线程池实现。并且有一个作业队列,在你把任何东西放到队列之前,你可以在那里检查它。
您可以将这些作业设置为可运行,并为每项作业提供UUid。你可以删除它们,用你随心所欲地打断它们。
这是一个cool example,复杂,但工作正常:)