Android 如何将 IntentService 的结果返回到 Activity 中?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10334901/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 03:20:22  来源:igfitidea点击:

How to get results from an IntentService back into an Activity?

androidandroid-intent

提问by gcl1

I am using an IntentService to handle network communications with a server via JSON. The JSON/server part is working fine, but I'm having trouble getting the results back where they are needed. The following code shows how I am starting the intent service from inside onClick(), and then having the service update a global variable to relay the results back to the main activity.

我正在使用 IntentService 通过 JSON 处理与服务器的网络通信。JSON/服务器部分工作正常,但我无法将结果返回到需要的地方。以下代码显示了我如何从 onClick() 内部启动意图服务,然后让服务更新全局变量以将结果中继回主活动。

public class GXActivity extends Activity {

    private static final String TAG = "GXActivity";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // === called when the activity is first created

        Log.i(TAG, "GXActivity Created");

        super.onCreate(savedInstanceState);
        setContentView(R.layout.start);

        View.OnClickListener handler = new View.OnClickListener() {
            public void onClick(View v) {

                // === set up an application context to hold a global variable
                // === called user, to contain results from the intent service
                GXApp appState = ((GXApp) getApplicationContext());
                User user = new User(-1); // initialize user id to -1
                appState.setUser(user);

                // === next start an intent service to get JSON from the server;
                // === this service updates the user global variable with
                // === results from the JSON transaction
                Intent intent = new Intent(this, GXIntentService.class);
                startService(intent);

                // === check app context for results from intent service
                appState = ((GXApp) getApplicationContext());
                if (appState.getUser().getId() != -1)...

            }
        }
    }
}

The problem I'm having is that the intent service that parses the JSON doesn't get invoked until after onCreate() completes, so my code that's looking for the results is stuck looking at uninitialized results.

我遇到的问题是解析 JSON 的意图服务直到 onCreate() 完成后才会被调用,所以我正在寻找结果的代码在查看未初始化的结果时被卡住了。

What should I do differently so the intent service gets called before I check the results? Would it work if I pulled the click listener out of the onCreate() function? Is there a another/better to structure this code? Many thanks.

我应该怎么做才能在检查结果之前调用 Intent 服务?如果我从 onCreate() 函数中拉出点击侦听器,它会起作用吗?是否有另一个/更好的结构此代码?非常感谢。

回答by tomtheguvnor

You should look at creating your own ResultReceiversubclass in your activity. ResultReceiverimplements Parcelableso can be passed from your Activityto your Serviceas an extra on the Intent.

您应该考虑ResultReceiver在您的活动中创建您自己的子类。ResultReceiver实现Parcelable因此可以从您的传递Activity到您的Service作为Intent.

You'll need to do something like this:

你需要做这样的事情:

  1. Implement a subclass of ResultReceiverwithin your activity class. The key method to implement is onReceiveResult(). This method provides you a with Bundleof result data which can be used to pass whatever information you are retrieving in your Service. Simply unpack the data you need and use it to update your activity.

  2. In your activity, create a new instance of your custom ResultReceiverand add it to the Intentyou use to start your service.

  3. In your Service's onStartCommand()method, retrieve the ResultReceiverpassed in on the Intentand store it in a local member variable.

  4. Once your Servicecompletes its work, have it call send()on the ResultReceiver passing whatever data you want to send back to the activity in a Bundle.

  1. ResultReceiver在您的活动类中实现一个子类。实现的关键方法是onReceiveResult(). 此方法为您提供了一个Bundle结果数据,可用于传递您在Service. 只需解压缩您需要的数据并使用它来更新您的活动。

  2. 在您的活动中,创建自定义的新实例ResultReceiver并将其添加到Intent用于启动服务的 。

  3. 在您ServiceonStartCommand()方法中,检索ResultReceiver传入的Intent并将其存储在本地成员变量中。

  4. 一旦你Service完成了它的工作,让它调用send()ResultReceiver 将你想要发送回活动的任何数据传递给Bundle.

This is a pretty effective pattern and means you're not storing data in nasty static variables.

这是一种非常有效的模式,意味着您不会将数据存储在讨厌的静态变量中。

回答by DSoldo

There's many ways to do stuffs in background getting back a result (AsyncTask, bind an Activity to a Service...), but if you want to mantain your IntentService's code you can simply:

有很多方法可以在后台做一些事情来获取结果(AsyncTask,将一个活动绑定到一个服务......),但是如果你想维护你的 IntentService 的代码,你可以简单地:

1- send a broadcast intent (that contains the status in its extended data) at the end of the work in your IntentService

1- 在您的 IntentService 工作结束时发送广播意图(包含其扩展数据中的状态)

2- implement a LocalBroadcastReceiver in your Activity that consumes the data from the Intent

2- 在您的 Activity 中实现一个 LocalBroadcastReceiver 来消耗来自 Intent 的数据

This is also the recommended way in the official documentation (if you want to mantain your IntentService):

这也是官方文档中推荐的方式(如果你想维护你的 IntentService):

https://developer.android.com/training/run-background-service/report-status.html

https://developer.android.com/training/run-background-service/report-status.html

回答by Yusuf X

If all you need to do is get a JSON from the server without locking up the UI thread, it may be simpler to just use AsyncTask.

如果您需要做的只是从服务器获取 JSON 而不锁定 UI 线程,那么使用AsyncTask可能会更简单。

回答by Prashanth Debbadwar

You can use Ottolibrary. Otto is an Open Source project designed to provide an event bus implementation so that components can publish and subscribe to events.

您可以使用奥托图书馆。Otto 是一个开源项目,旨在提供事件总线实现,以便组件可以发布和订阅事件。