Являются ли статические поля в классах Деятельности гарантированно переживать цикл create/destroy?

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

Как простой способ сохранить состояние, я думал, что, поскольку класс загружается только один раз загрузчиком класса, было бы безопасно хранить временные данные, которые были разделены между несколькими экземплярами активности в статичном поле Bundle.

Однако иногда, когда экземпляр A создает статический пакет и сохраняет в нем данные, он затем уничтожается, и экземпляр B пытается его прочитать, статическое поле внезапно становится NULL.

Не означает ли это, что класс был удален и перезагружен загрузчиком классов, когда активность проходила цикл create/destroy? Как иначе статическое поле вдруг станет NULL, когда оно ссылалось на объект раньше?

Ответы

Ответ 1

Первая часть этого ответа действительно старая - см. ниже правильный способ сделать это

Вы можете использовать объект Application для хранения постоянных объектов приложений. Этот Android FAQ также говорит об этой проблеме.

Что-то вроде этого:

public class MyApplication extends Application{
    private String thing = null;

    public String getThing(){
        return thing;
    }

    public void setThing( String thing ){
        this.thing = thing;
    }
}

public class MyActivity extends Activity {
    private MyApplication app;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        app = ((MyApplication)getApplication());

        String thing = app.getThing();
    }
}

Правильный путь:

Когда этот ответ был впервые написан, документация для жизненного цикла Activity была не такой хорошей, как сейчас. Чтение Раздел "Состояние сохранения" в документе "Деятельность" помогает нам понять, как Android хочет, чтобы мы сохранили состояние. По сути, есть два обстоятельства, при которых начинается ваша деятельность: (1) как новое действие и (2) из-за изменения конфигурации или когда он воссоздается после уничтожения из-за давления памяти. Когда ваша активность начинается, потому что это новая активность, тогда saveInstanceState имеет значение NULL. В противном случае это не имеет значения. Если он равен нулю, ваша деятельность должна инициализироваться с нуля. Фрагменты очень похожи на действия, и я подробно рассмотрел эту концепцию для слайд-панели AnDevCon-14. Вы также можете ознакомиться с образцом кода для моей презентации AnDevCon-14 для более подробной информации.

Переработка моего предыдущего примера будет выглядеть примерно так, как показано ниже. Я немного изменяю семантику - в этой второй версии я предполагаю, что строка thing специфична для действия в рамках конкретной задачи

Ответ 2

Другой, а также злой способ сохранить статические данные - значит, чтобы вы активировали один класс Singleton. Этот синглтон сохранит статическую ссылку на себя.

class EvilSingleton{
    private static EvilSingleton instance;

    //put your data as non static variables here

    public static EvilSingleton getInstance()
    {
        if(instance == null)
            instance = new EvilSingleton();
        return instance;
    }
}

В методе onCreate() вашей активности вы можете получить доступ/построить синглтон и любые данные, которые могут вам понадобиться. Таким образом, ваша деятельность или приложение могут быть уничтожены или воссозданы любое количество раз, и пока пространство памяти вашего процесса будет сохранено, вы должны быть в порядке.

Это злой подрывной хак, поэтому no promises; -)