Чистое связывание/отключение к службе в приложении
У меня есть приложение для Android, которое привязывается к постоянному сервису (однажды началось с startService()
).
Услуга является неотъемлемой частью приложения и, таким образом, используется практически в каждом мероприятии. Следовательно, я хочу привязать к службе только один раз (вместо привязки/развязывания в каждом Activity) и сохранить привязку во время жизни моего приложения.
Я расширился от Application и привязался к сервису в приложении # onCreate(), Однако у меня теперь есть проблема, что я не знаю, когда мое приложение существует, поскольку Application # onTerminate() никогда не вызывается, см. JavaDoc:
Этот метод предназначен для использования в эмулируемых средах процессов. Это никогда не будет быть вызваны на производственном устройстве Android, где процессы удаляются просто убивая их; никакой код пользователя (включая этот обратный вызов) не является выполняются при этом.
Итак, как я могу полностью отвязать привязку к службе в приложении?
Ответы
Ответ 1
Я решил эту проблему, посчитав ссылки на привязку службы в Application
. Каждый Activity
должен вызывать acquireBinding()
в своих методах onCreate()
и вызывать releaseBinding()
в onDestroy()
. Если контрольный счетчик достигает нуля, связывание освобождается.
Вот пример:
class MyApp extends Application {
private final AtomicInteger refCount = new AtomicInteger();
private Binding binding;
@Override
public void onCreate() {
// create service binding here
}
public Binding acquireBinding() {
refCount.incrementAndGet();
return binding;
}
public void releaseBinding() {
if (refCount.get() == 0 || refCount.decrementAndGet() == 0) {
// release binding
}
}
}
// Base Activity for all other Activities
abstract class MyBaseActivity extend Activity {
protected MyApp app;
protected Binding binding;
@Override
public void onCreate(Bundle savedBundleState) {
super.onCreate(savedBundleState);
this.app = (MyApp) getApplication();
this.binding = this.app.acquireBinding();
}
@Override
public void onDestroy() {
super.onDestroy();
this.app.releaseBinding();
}
}
Ответ 2
От ответа Свена:
Я решил эту проблему, сославшись на ссылки на сервис привязки в приложении. Каждое действие должно вызвать приобретатьBinding() в своих методах onCreate() и call releaseBinding() в onDestroy(). Если контрольный счетчик достигает нуля, привязка освобожден.
Я согласен, НО вы не должны делать это в onDestroy - это часто не будет вызвано.
Вместо этого я предлагаю следующее (на основе вашего образца кода)...
// Base Activity for all other Activities
abstract class MyBaseActivity extend Activity {
protected MyApp app;
protected Binding binding;
@Override
public void onCreate(Bundle savedBundleState) {
super.onCreate(savedBundleState);
this.app = (MyApp) getApplication();
this.binding = this.app.acquireBinding();
}
@Override
protected void onPause() {
super.onPause();
// Pre-HC, activity is killable after this.
if ((11 > Build.VERSION.SDK_INT) && (isFinishing()))
onFinishing();
}
@Override
protected void onStop() {
super.onStop();
if ((10 < Build.VERSION.SDK_INT) && (isFinishing()))
onFinishing();
}
protected void onFinishing() {
// Do all activity clean-up here.
this.app.releaseBinding();
}
}
НО, мое использование isFinishing() - это просто мысль - я не уверен, что она надежна. Возможно, onPause/onStop вызывается с isFinishing() false, но тогда активность убивается - и ваш releaseBinding() никогда не вызывается.
Если вы избавитесь от проверки isFinishing, я думаю, вам нужно переместить вызов purchaseBinding() из onCreate в onStart/onResume (в зависимости от версии sdk), чтобы убедиться, что ваш счетчик ссылок не запутался.
Кто знал, что освобождение вашего приложения будет настолько сложным!
Ответ 3
В этом случае неотъемлемая необходимость? В любом случае приложение будет убито. Я попробовал реализовать пример приложения, делающего это без развязки, и, похоже, работает правильно.