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

Чистое связывание/отключение к службе в приложении

У меня есть приложение для Android, которое привязывается к постоянному сервису (однажды началось с startService()).

Услуга является неотъемлемой частью приложения и, таким образом, используется практически в каждом мероприятии. Следовательно, я хочу привязать к службе только один раз (вместо привязки/развязывания в каждом Activity) и сохранить привязку во время жизни моего приложения.

Я расширился от Application и привязался к сервису в приложении # onCreate(), Однако у меня теперь есть проблема, что я не знаю, когда мое приложение существует, поскольку Application # onTerminate() никогда не вызывается, см. JavaDoc:

Этот метод предназначен для использования в эмулируемых средах процессов. Это никогда не будет быть вызваны на производственном устройстве Android, где процессы удаляются просто убивая их; никакой код пользователя (включая этот обратный вызов) не является выполняются при этом.

Итак, как я могу полностью отвязать привязку к службе в приложении?

4b9b3361

Ответ 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

В этом случае неотъемлемая необходимость? В любом случае приложение будет убито. Я попробовал реализовать пример приложения, делающего это без развязки, и, похоже, работает правильно.