Запустите IntentService из Activity и обновите Activity по окончании IntentService. - PullRequest
26 голосов
/ 01 февраля 2012

В моем приложении для Android у меня есть простое представление списка с адаптером.Есть тяжелый запрос, который должен заполнить представление списка данными.Поэтому я помещаю его в IntentService, который выполняется в другом потоке.

IntentService обычно работает отдельно, просто для запроса некоторых данных и вставки их в базу данных SQLite.

НоТеперь я хотел бы иметь следующую возможность:

  1. Действие запускает IntentService с startService ().
  2. IntentService выполняет свою тяжелую работу.
  3. КогдаIntentService завершен, он должен проинформировать действие о результате, чтобы можно было обновить действие, чтобы отобразить новые данные.

Возможно ли это?Я прочитал много вопросов здесь о переполнении стека на эту тему.Но в каждом вопросе было другое решение.Поэтому я хочу спросить вас всех: какое решение лучше всего подходит для моих целей?

  • Привязка IntentService к Деятельности, похоже, не является лучшим решением, поскольку могут возникнуть конфликты с изменениями конфигурацииактивность и т. д. Правильно?
  • В этом блоге предлагается использовать AIDL с Parcelables - что для меня звучит очень сложно.Есть более простой способ, не так ли?
  • Можно настроить приемник вещания в действии и запустить его в IntentService, когда он закончится.
  • Некоторые люди говорят, что вы должны используйте createPendingResult () для передачи PendingIntent в IntentService.Если IntentService обнаруживает, что PendingIntent в своих дополнениях, он использует это для запуска onActivityResult () в Activity.Это способ выбрать?

Ответы [ 5 ]

23 голосов
/ 01 февраля 2012

В качестве примера я использую 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);
12 голосов
/ 20 марта 2014

Ни один из других ответов не ссылается на официальную документацию по Android

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

, в которой четко указано, что для связи Activity-IntentService "Рекомендуемый способ отправки и получения статуса заключается в использованииLocalBroadcastManager, который ограничивает широковещательные объекты Intent компонентами в вашем собственном приложении "!

12 голосов
/ 06 октября 2013

Когда 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"));
}

Для получения дополнительной информации см. Сообщение в блоге Использование LocalBroadcastManager В службе связи с деятельностью .

3 голосов
/ 01 февраля 2012

Я бы предложил использовать Broadcast Receiver в The Activity в ожидании результата.Ваша служба будет просто использовать sendBroadcast с пользовательским Intent.

2 голосов
/ 21 апреля 2014

Я думаю, что автобус для мероприятий - это путь. Простое и эффективное межпроцессное взаимодействие.

...