Подтвердить что ты не робот

Запустите IntentService из Activity и обновите Activity, когда IntentService закончен

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

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

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

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

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

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

Ответ 1

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

Ответ 2

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

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

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

Ответ 3

Когда 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 в службе связи для связи.

Ответ 4

Я бы предложил использовать широковещательный приемник в ожидании результата. Ваша Служба просто использовала бы sendBroadcast с пользовательским Intent.