43

我正在使用 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)...

            }
        }
    }
}

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

我应该做些什么不同的事情,以便在我检查结果之前调用意图服务?如果我将点击监听器从 onCreate() 函数中拉出来,它会起作用吗?是否有另一个/更好的方式来构建此代码?非常感谢。

4

4 回答 4

86

您应该考虑在活动中创建自己的ResultReceiver子类。ResultReceiver实现,Parcelable因此可以作为.ActivityServiceIntent

你需要做这样的事情:

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

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

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

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

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

于 2012-04-26T14:11:12.090 回答
12

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

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

2- 在您的 Activity 中实现一个 LocalBroadcastReceiver ,它使用来自 Intent 的数据

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

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

于 2014-03-20T15:07:04.843 回答
7

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

于 2012-04-26T14:18:09.013 回答
1

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

于 2015-07-07T07:18:46.187 回答