【问题标题】:How to wait for an IntentService to finish its task如何等待 IntentService 完成其任务
【发布时间】:2014-08-14 23:06:17
【问题描述】:

我正在使用意图服务与服务器通信以获取应用程序的数据。我希望应用程序等到它请求的数据被发回(希望意味着请求数据的 IntentService 已完成运行),然后应用程序尝试访问或使用要存储数据的变量. 我该怎么做呢?谢谢!

【问题讨论】:

  • “我希望应用等待”——请更具体一些。什么是“应用程序”? “在应用程序尝试访问或使用数据变量之前”是什么意思?
  • 我希望它在意图服务发出 http 请求时不做任何事情(我的意思是与服务器通信)。然后一旦该请求返回,执行操作,该操作是我想对数据执行的多个不同处理步骤。该应用程序,即我正在开发的应用程序正在使用意图服务与服务器进行通信(发出 http 请求)。
  • “我想要”——什么是“它”?请贴出“it”的源代码,或者至少说出具体的Android类“it”是什么。我们无法知道“它”是什么。我们所知道的是“它”不是IntentService,顺便说一句,你正在构建你的句子,但这并不多。 “意思是我正在开发的应用程序”——这是一个循环定义。 Android 开发人员编写活动、服务、内容提供者、广播接收器以及这些组件使用的东西。就这些 Android 结构而言,“它”和“应用程序”是什么?
  • 它是应用程序。我正在开发的应用程序,这就是我问这个问题的原因。使用意图服务发出 http 请求的应用程序。我要处理从这些 http 请求返回的数据的应用程序。我只想知道当通过 Intent 服务发出的 http 请求完成并返回数据时如何通知应用程序,并且在返回数据之前让应用程序不执行任何操作。

标签: android rest intentservice android-internet android-async-http


【解决方案1】:

最简单的方法是让您的IntentService 在从服务器收集数据后发送一个Broadcast,您可以在您的 UI 线程中收听该数据(例如Activity)。

public final class Constants {
    ...
    // Defines a custom Intent action
    public static final String BROADCAST_ACTION =
        "com.example.yourapp.BROADCAST";
    ...
    // Defines the key for the status "extra" in an Intent
    public static final String EXTENDED_DATA_STATUS =
        "com.example.yourapp.STATUS";
    ...
}

public class MyIntentService extends IntentService {
    @Override
    protected void onHandleIntent(Intent workIntent) {
        // Gets data from the incoming Intent
        String dataString = workIntent.getDataString();
        ...
        // Do work here, based on the contents of dataString
        // E.g. get data from a server in your case
        ...

        // Puts the status into the Intent
        String status = "..."; // any data that you want to send back to receivers
        Intent localIntent =
            new Intent(Constants.BROADCAST_ACTION)
                    .putExtra(Constants.EXTENDED_DATA_STATUS, status);
        // Broadcasts the Intent to receivers in this app.
        LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
    }
}

然后创建您的广播接收器(您的 Activity 中的单独类或内部类)

例如

// Broadcast receiver for receiving status updates from the IntentService
private class MyResponseReceiver extends BroadcastReceiver {
    // Called when the BroadcastReceiver gets an Intent it's registered to receive
    @
    public void onReceive(Context context, Intent intent) {
        ...
        /*
         * You get notified here when your IntentService is done
         * obtaining data form the server!
         */
        ...
    }
}

现在最后一步是在您的 Activity 中注册 BroadcastReceiver:

IntentFilter statusIntentFilter = new IntentFilter(
      Constants.BROADCAST_ACTION);
MyResponseReceiver responseReceiver =
      new MyResponseReceiver();
// Registers the MyResponseReceiver and its intent filters
LocalBroadcastManager.getInstance(this).registerReceiver(
      responseReceiver, statusIntentFilter );

【讨论】:

  • 好的,所以,好的答案,是的。但不是我想要的。我已经执行了上述所有操作,但是,现在,鉴于我已经完成了,假设我将一个返回字符串的意图交给我的 IntentService,然后在我发送该意图后的某个时间点,我拨打电话到结果字符串。如果我没有等待,我可能会在该字符串被填充之前,在意图返回之前调用它。特别是在我的情况下,我从广播接收器获取字符串。如果我在接收者收到它的广播之前调用它,空指针异常。
  • 最好进行空检查并通知用户重试该操作(因为可能发生的唯一方法是用户首先启动了该事件序列!),或者应用程序跟踪该状态(即用户想要执行该操作)并在从服务器接收到字符串后自动执行它。最好保留一个状态变量并适当地处理这些场景,除非您想在执行后台任务时阻止 UI。使用 AsycTask 显示一个微调器对话框,直到从服务器接收到所需的数据)
  • 在执行后台任务时基本上有三个选项: 1. 阻止整个 UI 并阻止用户执行操作,直到后台操作完成。 2. 只阻塞 UI 中的某些元素,直到后台操作完成(需要非常小心状态转换和导航到其他活动/片段)。 3. 让用户做任何事情,但如果用户尝试做不可能的事情(例如,尝试使用您正在谈论的字符串可用之前做某事),则向用户提供适当的反馈。
  • 所以,您发表的第二条评论。如何跟踪“状态”?这听起来正是我想做的事情。
  • 保留一个布尔值(例如 isInvokingService),在调用服务操作之前将其设置为 true。然后在 MyResponseReceiver 中将其设置回 false (将其设为匿名类以使事情更简单)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-26
  • 2021-10-21
  • 1970-01-01
相关资源
最近更新 更多