如何等待IntentService完成其任务

4

我正在使用Intent Service与服务器通信,以获取应用程序的数据。我希望应用程序在访问或使用存储数据的变量之前等待它请求的数据已经被发送回来(希望这意味着从中请求数据的IntentService已经完成运行)。我该如何做到这一点?谢谢!


“我希望应用程序等待” - 请更具体地说明。什么是“应用程序”?您所说的“在应用程序尝试访问或使用变量数据之前”是什么意思? - CommonsWare
我希望在意图服务进行HTTP请求时它不做任何事情(我的意思是与服务器通信)。然后,一旦该请求返回,执行操作,该操作是我想要使用数据执行的多种不同处理步骤。这个应用程序是指我正在使用意图服务与服务器通信(进行HTTP请求)的应用程序。 - bgenchel
“我希望它” - “它”是什么?请发布“它”的源代码,或者至少说明“它”是哪个特定的Android类。我们无法知道“它”是什么。从你构造的句子中可以得知,“它”不是IntentService,但这并不能提供太多信息。“我的意思是我正在开发的应用程序” - 这是一个循环定义。Android开发人员编写活动、服务、内容提供程序、广播接收器以及这些组件使用的东西。在这些Android构造方面,“它”和“应用程序”是什么? - CommonsWare
这是一个关于应用程序开发的内容。我正在开发一个应用程序,这就是为什么我要问这个问题的原因。该应用程序使用意图服务来进行HTTP请求。我想处理从这些HTTP请求返回的数据的应用程序。我只想知道当通过意图服务进行的HTTP请求完成并返回数据时,如何通知应用程序,并且在返回数据之前不执行任何操作。 - bgenchel
1个回答

8
最简单的方法是让你的IntentService在从服务器收集完数据后发送一个广播,然后在你的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,该意图将返回一个字符串,然后在发送该意图后的某个时刻,我调用该结果字符串。如果我没有等待,那么有可能在意图返回之前就调用了该字符串。具体来说,在我的情况下,我正在从广播接收器中获取字符串。如果在接收器接收到其广播之前调用它,则会出现空指针异常。 - bgenchel
最好进行空值检查并通知用户再次尝试该操作(因为唯一可能发生的情况是用户首先启动了该事件序列!),或者应用程序跟踪该状态(即用户想要执行该操作)并在从服务器接收到字符串后自动执行它。最好保留一个状态变量并适当处理这些情况,除非您希望在执行后台任务时阻止UI。使用AsycTask显示旋转对话框,直到从服务器接收到所需数据。 - Thira
1
在执行后台任务时,基本上有三个选项:
  1. 阻塞整个UI,并防止用户进行操作直到后台操作完成。
  2. 仅阻塞UI中的某些元素,直到后台操作完成(需要非常小心状态转换和导航到其他活动/片段)。
  3. 让用户随意操作,但如果他们尝试做不可能的事情(例如,在之前提到的字符串可用之前尝试使用它),则向用户提供适当的反馈。
- Thira
那么,你提出的第二个评论。如何跟踪“状态”?这听起来正是我想做的。 - bgenchel
保持一个布尔值(例如isInvokingService),在调用服务操作之前将其设置为true。然后在MyResponseReceiver中将其设置回false(将其设置为匿名类以使事情更简单)。 - Thira

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