Android: 理解如何使用一个IntentService处理多个操作

3
我有一个问题,意图无法在特定的活动流程下传递到 IntentService:以下是场景:
1. 考虑三个活动,主页、B 和 C。C 有两个片段 CF1 和 CF2。 2. B、CF1 和 CF2 使用相同的 IntentService 类,但使用不同的操作。 3. 启动 IntentService 使用 startService(Intent)。(对于片段,请使用 getActivity().startService(Intent)) 4. 在 IntentService 启动的任何地方,如果它在 Activity/Fragment 的 onStop() 中运行,则确保使用 stopService(intent) 将其停止。 5. 如果活动流程是 Home -> C -> CF1 -> CF2,则一切正常。 6. 如果活动流程是 Home -> B -> C -> CF1 -> CF2,则在从 CF2 的 startService(Intent) 开始后,onHandleIntent 永远不会被调用。B 和 CF1 意图已处理。为了调试,我尝试等待 IntentService 在活动 B 中完成,然后进入 CF1 -> CF2,仍然存在相同的问题。CF1 似乎永远没有启动相同意图服务的任何问题。当我为 CF2 尝试创建一个新的 IntentService 类时,它能够工作。
我的理解是,IntentService 有一个意图队列。如果服务第一次运行,会调用 onStartCommand(我们不应该处理 IntentService)。如果服务已经运行,每次调用 startService 都会调用 onHandleIntent。
显然,我做错了什么,但不清楚是什么。我尝试查看其他 Stack Overflow 问题,但没有帮助。我使用的代码非常简单:
AndroidManifest.xml
<service android:name=".service.ExampleIntentService" />

Activity B

@Override
public void onCreate(Bundle savedInstanceState)
{
       .......
       intent = new Intent(getApplicationContext(), ExampleIntentService.class);
       intent.setAction(StringConstants.ACTION_B);
       serviceRunning = true; //set to false in onReceiveResult 
       startService(intent);
}

@Override
public void onStop()
{
      if(serviceRunning && intent != null)
          stopService(intent)
}

Fragment CF1

@Override
public void onResume()
{
    super.onResume();

    intent = new Intent(getActivity(), ExampleIntentService.class);
    intent.setAction(StringConstants.ACTION_CF1);
    serviceRunning = true; //set to false in onReceiveResult 
    startService(intent);
}

@Override
public void onStop()
{
      if(serviceRunning && intent != null)
          stopService(intent)
}

片段和CF2的代码完全相同


IntentService不会排队意图。对于每个传入的意图,都会调用startService;所有调用都会排队在服务本地的Looper线程上。虽然在服务不执行任何操作时停止服务是一种良好的实践,但这只是一种优化。我建议你在应用程序正常工作之前不要这样做。 - G. Blake Meike
@G.BlakeMeike 我不理解“不排队意图”和“调用在服务本地的Looper线程上排队”的区别。我将尝试调用stopService并查看结果。但是创建一个单独的IntentService是否更好?我知道那样可以解决问题。另外,我不确定为什么在片段CF1中没有看到相同的问题。 - Prasanna
区别在于,意图(intents)总是传递给IntentService.startService。startService方法将调用排队到本地队列中,然后由另一个线程将其作为调用传递到onHandleIntent中。所有的调用都是如此。请参见下面Mark的答案:停止调用stopService。 - G. Blake Meike
1个回答

6
我的理解是...如果服务第一次运行,将调用onStartCommand(我们不应该处理IntentService);如果服务已经在运行,则对每个后续的startService调用都会调用onHandleIntent。
不。每次startService调用都会调用onStartCommand()。除非您在onStartCommand()中执行某些操作以更改正常行为,否则对于每个发往IntentService的startService调用,都会调用onHandleIntent()。
IntentService使用startService(Intent)启动。
您可以使用startService()向IntentService发送命令。
无论IntentService在何处启动,我都会确保使用stopService(intent)停止它,这是一个非常糟糕的想法。如文档所述,IntentService将在处理完所有startService()调用后自行停止。
IntentService将接收Intents,启动工作线程,并在适当时停止服务。

像 @G.BlakeMeike 和你说的那样,我尝试删除了 stopService 并且成功了。但我还是不确定,当用户离开一个正在运行 IntentService 的活动时,正确的方法是什么?你说这是个坏主意,难道我们不应该在用户离开该活动时停止服务吗? - Prasanna
2
@Prasanna:使用IntentService的原因是因为你希望工作在用户离开活动时继续进行。如果你不想要这个,就不要使用IntentService--只需使用线程即可。 - CommonsWare

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接