Как сохранить сложный объект при перезапуске Activity? - PullRequest
22 голосов
/ 28 октября 2009

Скажем, у меня есть объект Java Bean, который можно сериализировать. Я хочу сохранить его в безопасном месте, когда действие проходит через onDestroy () с целью (т.е. onSaveInstanceState () не вызывается).

Я ищу способ, который не включает создание базы данных и запись объекта в нее (в основном, из-за того, что а) API БД Android ужасен и б) поскольку базы данных превращают обновления приложений в кошмар, потому что нет достойной поддержки для применения миграций).

Я думал о сериализации объекта в ByteArrayOutputStream, base64 его кодирует и записывает в файл SharedPreferences в виде строки. Или это слишком далеко?

UPDATE

Может быть, идея сериализации в строку не так уж и плоха, похоже, работает неплохо. Вот что я делаю сейчас:

    public static String objectToString(Serializable object) {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    try {
        new ObjectOutputStream(out).writeObject(object);
        byte[] data = out.toByteArray();
        out.close();

        out = new ByteArrayOutputStream();
        Base64OutputStream b64 = new Base64OutputStream(out);
        b64.write(data);
        b64.close();
        out.close();

        return new String(out.toByteArray());
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

public static Object stringToObject(String encodedObject) {
    try {
        return new ObjectInputStream(new Base64InputStream(
                new ByteArrayInputStream(encodedObject.getBytes()))).readObject();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

в onDestroy () Затем я могу просто записать строку Base64 в файл настроек, где безопасно, пока я не прочитаю ее снова во время следующего запуска действия. Это намного быстрее, чем я ожидал, и если ваши бины не переносят огромные объемы данных, это работает довольно хорошо. И что еще лучше, вам не нужно поддерживать схему БД.

Тем не менее, мне любопытно, как другие делают это.

Ответы [ 2 ]

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

Я ищу способ, который не привлекать создание базы данных и писать объект к этому (в основном, так как) API БД Android ужасен и б) поскольку базы данных делают заявку обновляет кошмар, потому что есть нет достойной поддержки для подачи заявления Миграции).

API Android на самом деле довольно разумный, в основном потому, что он представляет собой тонкую оболочку над API SQLite, а API SQLite вполне приемлем для встроенной базы данных. Более того, Android предоставляет помощь в обновлении схемы при обновлении приложений через SQLiteOpenHelper.

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

Я слышал о том, что от сериализации убегает гораздо больше разработчиков, чем о людях, которые добились успеха в этом. Буквально в последние несколько дней, здесь, на SO #android, у меня произошел обмен с кем-то, кто отчаянно пытался вырвать сериализацию из его приложения у корней.

И что еще лучше, вам не нужно поддерживать схему БД.

О да, вы делаете. Как вы думаете, что произойдет, когда вы обновите свое приложение и ваш класс будет изменен? Ведение бухгалтерии , чтобы выяснить, как десериализовать старые версии класса из новой версии класса, является рутиной и является одной из причин, по которой разработчики отказываются от сериализации. Также не забывайте, что сериализация не является транзакционной, тогда как SQLite - это.

3 голосов
/ 16 февраля 2013

Я также искал хороший подход для отмены / маршалинга любых бинов или состояний активности. Мы все знаем, насколько onStoreInstanceState () и onRestoreInstanceState () в Activity - это боль.

Моя деятельность просто сохраняет свои состояния в onPause () и восстанавливает их в хуках жизненного цикла onCreate () с помощью прямой сериализации объектов.

Сериализация через строку, как вы делаете, конечно, возможна, но менее подходит для больших данных и вызывает много накладных расходов. Более того, предпочтения на самом деле существуют для хранения предпочтений, а не данных :) К сожалению, Parcelable / Parcel, который мы могли бы использовать для этой цели, не рекомендует хранить в постоянном хранилище.

Итак, осталась лишь простая сериализация объектов - к счастью, в Android SDK реализованы классы ObjectInputStream и ObjectOutputStream со всеми недостатками и преимуществами - как мы это сделали бы и в мире без Android, просто:

ObjectOutputStream.writeObject(yourPojo)

сделало бы для нас магию (не забудьте реализовать Serializable marker-interface)

Кроме того, вы можете обратиться к следующим API-интерфейсам Context - ContextWrapper - Activity, которые очень полезны для кэширования локальных данных (например, изображений) и т. Д .:

.getCacheDir()
.getDir()
.openFileInput()
.openFileOutput()

счастливого взлома:)

...