从Activity启动IntentService并在IntentService完成时刷新Activity

时间:2012-01-31 22:58:29

标签: android multithreading android-intent broadcastreceiver android-activity

在我的Android应用程序中,我有一个带适配器的简单列表视图。有一个繁重的查询是用数据填充列表视图。所以我把它放到另一个线程中运行的IntentService。

IntentService通常单独运行,只是为了查询一些数据并将其插入到SQLite数据库中。

但现在我希望有以下可能性:

  1. 活动使用startService()启动IntentService。
  2. IntentService工作繁重。
  3. 当IntentService完成后,它应通知活动有关结果的信息,以便刷新活动以显示新数据。
  4. 这可能吗?我在这个主题的Stack Overflow上阅读了很多问题。但在每个问题中,都有另一种解决方案。所以我想问你们所有人:哪种解决方案最符合我的目的?

    • 将IntentService绑定到Activity似乎不是最佳解决方案,因为可能存在与活动等配置更改的冲突。正确吗?
    • This blog post建议将AIDL与Parcelables一起使用 - 这对我来说听起来非常复杂。有一种更简单的方法,不是吗?
    • 可以在活动中设置广播接收器,并在完成后在IntentService中触发此广播。
    • 有人说你应该use createPendingResult() to pass a PendingIntent到IntentService。如果IntentService在其附加内容中发现PendingIntent,则使用它来触发Activity中的onActivityResult()。这是选择的方式吗?

5 个答案:

答案 0 :(得分:23)

例如,我使用ResultReceiver在我的notifyDataSetChanged()(扩展Activity)的适配器上调用ListActivity。它可以适应你需要做的任何事情。

ResultReceiver代码:

public class MyResultReceiver extends ResultReceiver {

    private Context context = null;

    protected void setParentContext (Context context) {
        this.context = context;
    }

    public MyResultReceiver(Handler handler) {
        super(handler);
    }

    @Override
    protected void onReceiveResult (int resultCode, Bundle resultData) {

        // Code to process resultData here

        ((BaseAdapter) ((ListActivity)context).getListAdapter()).notifyDataSetChanged();
    }
}

MyActivity代码:

public class MyActivity extends ListActivity {

    private MyResultReceiver theReceiver = null;

    ...

    private void callService () {
        theReceiver = new MyResultReceiver(new Handler());
        theReceiver.setParentContext(this);
        Intent i = new Intent("com.mycompany.ACTION_DO_SOMETHING");

        // Code to define and initialize myData here

        i.putExtra("someData", myData);
        i.putExtra("resReceiver", theReceiver);
        startService(i);

    }
}

IntentService代码:

Bundle resultBundle = new Bundle();
ResultReceiver resRec = intent.getParcelableExtra("resReceiver");

// Do some work then put some stuff in resultBundle here

resRec.send(12345, resultBundle);

答案 1 :(得分:12)

当IntentService完成时,它应该使用LocalBroadcastManager向任何已注册的活动发送意图。

IntentService将包含如下代码:

private void sendBroadcast() {
    Intent intent = new Intent("myBroadcastIntent");
    intent.putExtra("someName", someValue);
    LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}

接收通知的活动将包含以下代码:

@Override
protected void onCreate(Bundle savedInstanceState) {
    // ...
    BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String someValue = intent.getStringExtra("someName");
            // ... do something ...
        }
    };
    LocalBroadcastManager.getInstance(this)
        .registerReceiver(receiver, new IntentFilter("myBroadcastIntent"));
}

有关详细信息,请参阅博文Using LocalBroadcastManager In Service To Activity Communications

答案 2 :(得分:12)

其他答案都没有引用官方的Android文档

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

明确指出,对于Activity-IntentService通信"发送和接收状态的推荐方法是使用LocalBroadcastManager,它将广播Intent对象限制为您自己应用中的组件"!

答案 3 :(得分:3)

我建议在The Activity中使用广播接收器等待结果。 您的服务只会将sendBroadcast与自定义Intent一起使用。

答案 4 :(得分:2)

我认为事件总线是要走的路。简单有效的进程间通信。