Гарантированы ли статические поля в классах Activity пережить цикл создания / уничтожения? - PullRequest
15 голосов
/ 28 октября 2009

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

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

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

Не означает ли это, что класс был удален и перезагружен загрузчиком классов, пока действие проходило через цикл создания / уничтожения? Как еще может static поле внезапно стать пустым, когда оно ранее ссылалось на объект?

Ответы [ 2 ]

13 голосов
/ 28 октября 2009

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

Вы можете использовать объект 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 slide slide . Вы также можете взглянуть на пример кода для моей презентации AnDevCon-14 для получения более подробной информации.

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

public class MyActivity extends Activity {
    private static final String THING = "THING";

    private String thing;

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

        if (savedInstanceState==null) {
            // First time here (since we last backed out at least)
            thing = initializeThing(); // somehow we init it
        } else {
            // Rehydrate this new instance of the Activity
            thing = savedInstanceState.getString(THING);
        }

        String thing = app.getThing();
    }

    protected void onSaveInstanceState(Bundle outState) {
        outState.putString(THING, thing);
    }
}
0 голосов
/ 28 октября 2009

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

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 () вашей деятельности вы можете получить доступ / создать синглтон и любые данные, которые вам могут понадобиться. Таким образом, ваша деятельность или приложение могут быть уничтожены или воссозданы любое количество раз, и если пространство памяти вашего процесса сохраняется, вы должны быть в порядке.

Это злой подрывной хак, так что никаких обещаний; -)

...