Симуляция isDestroyed() в Android

Я обнаружил, что мне нужно позвонить isDestroyed() проверить, является ли действие более недействительным. Я сделал это, и все работает отлично.

Тем не менее, включение isDestroyed() вынуждает меня поднять уровень API Android до уровня (17), который мне не нравится. Я бы предпочел не делать этого.

Я думаю, что я могу симулировать isDestroyed() просто переопределив onDestroy() в моей деятельности. Когда этот метод вызывается, я могу просто сохранить этот факт в логическом значении, а затем использовать его для предоставления своей собственной версии isDestroyed() (смена названия конечно).

Будет ли что-то так просто, как эта работа? Я вижу много ссылок на onDestroy() не вызывается в некоторых случаях. Есть ли другой способ симулировать это?

2 ответа

Видя, как код структуры:

public boolean isDestroyed() {
    return mDestroyed;
}

final void performDestroy() {
    mDestroyed = true;
    mWindow.destroy();
    mFragments.dispatchDestroy();
    onDestroy();
    if (mLoaderManager != null) {
        mLoaderManager.doDestroy();
    }
    if (mVoiceInteractor != null) {
        mVoiceInteractor.detachActivity();
    }
}

Я бы сказал, что вы достаточно безопасны, чтобы использовать свой собственный флаг, установленный в onDestroy, вы получите тот же результат, что и при использовании флага платформы, если что-то не падает mWindow.destroy() или же mFragments.dispatchDestroy()

Это может работать, в зависимости от того, когда вам нужно проверить isDestroyed(),

Если вы проверите для isDestroyed() в Fragment.onDestroy() обратный вызов, смоделированная реализация, реализованная, как вы описываете, вернет false, в то время как Activity.isDestroyed() вернусь true, Если вы проверите для isDestroyed() "позже", это будет работать. Вы можете проверить это с помощью следующего приложения для тестирования:

package com.example.test.myapplication;

import android.app.Activity;
import android.app.Fragment;
import android.os.Handler;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class MainActivity extends Activity {

    private boolean mOnDestroyCalled;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (savedInstanceState == null) {
            getFragmentManager().beginTransaction().add(R.id.container, new MainFragment())
                    .commit();
        }
    }

    @Override
    protected void onDestroy() {
        mOnDestroyCalled = true;
        super.onDestroy();
    }

    public boolean isDestroyed_SIMULATED() {
        return mOnDestroyCalled;
    }

    public static class MainFragment extends Fragment {
        @Override
        public void onDestroy() {
            super.onDestroy();
            final MainActivity mainActivity = (MainActivity)getActivity();
            dumpIsDestroyedImplementations("In Fragment.onDestroy() ", mainActivity);

            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    dumpIsDestroyedImplementations("A while later           ", mainActivity);
                }
            }, 500);
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            final TextView textView = new TextView(getActivity());
            textView.setText("Hello world!");
            return textView;
        }

        private void dumpIsDestroyedImplementations(String prefix, MainActivity mainActivity) {
            Log.i("IsDestroyedTest", prefix + "isDestroyed(): " +
                    mainActivity.isDestroyed() +
                    " isDestroyed_SIMULATED(): " + mainActivity.isDestroyed_SIMULATED());
        }
    }
}

Если вы запустите это, а затем нажмите кнопку Назад на устройстве, adb logcat -s IsDestroyedTest даст вам следующий вывод:

I/IsDestroyedTest( 2143): In Fragment.onDestroy() isDestroyed(): true isDestroyed_SIMULATED(): false
I/IsDestroyedTest( 2143): A while later           isDestroyed(): true isDestroyed_SIMULATED(): true

Чтобы понять почему, взгляните на то, как isDestroyed() реализовано.

public boolean isDestroyed() {
    return mDestroyed;
}

...

final void performDestroy() {
    mDestroyed = true;
    ...
    mFragments.dispatchDestroy();
    onDestroy();
    ...
}

В этом случае мы можем концептуально переписать его следующим образом:

final void performDestroy() {
    mDestroyed = true;
    ...
    MainFragment.onDestroy() // Called by mFragments.dispatchDestroy();
    mOnDestroyCalled = true; // From MainActivity.onDestroy()
    super.onDestroy(); // From MainActivity.onDestroy()
    ...
}

И легко понять, почему мы получаем вывод logcat, который мы получаем.

относительно onDestroy() не вызывая иногда, эта проблема не будет зависеть от моделирования isDestroyed(), И, как правило, если он не вызывается, на это есть веские причины (системе срочно нужно освободить память и не успеть завершить вызовы жизненного цикла действия, или нет причины фактически уничтожить действие). Относительно того, есть ли другие способы симулировать это, по крайней мере, я не могу думать ни о каком.

Другие вопросы по тегам