Запустите IntentService из Activity и обновите Activity, когда IntentService закончен
В моем приложении Android у меня есть простой вид списка с адаптером. Там тяжелый запрос, который должен заполнить представление списка данными. Поэтому я помещаю его в IntentService, который запускается в другом потоке.
IntentService обычно запускается отдельно самостоятельно, просто для запроса некоторых данных и вставки его в базу данных SQLite.
Но теперь я хотел бы иметь следующую возможность:
- Действие запускает IntentService с помощью startService().
- IntentService выполняет свою тяжелую работу.
- Когда IntentService будет завершен, он должен сообщить о действии о результатах, чтобы активность могла быть обновлена, чтобы показать новые данные.
Возможно ли это? Я прочитал много вопросов здесь о переполнении стека по этой теме. Но в каждом вопросе было другое решение. Поэтому я хочу спросить вас всех: какое решение лучше для моей цели?
- Привязка IntentService к Activity не кажется лучшим решением, так как могут возникнуть конфликты с изменениями конфигурации активности и т.д. Правильно?
- В этом сообщении в блоге предлагается использовать AIDL с Parcelables - что звучит очень сложно для меня. Есть более простой способ, не так ли?
- Можно настроить широковещательный приемник в своей активности и запустить эту трансляцию в IntentService, когда она будет завершена.
- Некоторые люди говорят, что вы должны использовать createPendingResult() для передачи PendingIntent в IntentService. Если IntentService обнаруживает, что PendingIntent в своих дополнениях, он использует это для запуска onActivityResult() в Activity. Это выбор?
Ответы
Ответ 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
.
Ответ 5
Я думаю, что автобус событий - это путь. Простая и эффективная межпроцессная связь.