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

Как сохранить состояние во время изменения ориентации в Android, если состояние сделано из моих классов?

Я смотрел, как Android обрабатывает изменение ориентации для моего приложения (я обнаружил, что он перезапускает mainactivity при изменении ориентации. Я видел, что вы можете переопределить метод

protected void onSaveInstanceState(Bundle outState)

Чтобы сохранить материал, вставьте его в onStart. Проблема в том, что у меня есть представление с пользовательскими объектами и списком с использованием пользовательского адаптера. Все в ArrayList этих объектов, но я заметил, что вы не можете помещать произвольные объекты в комплект! Итак, как мне сохранить состояние?

4b9b3361

Ответ 1

EDIT: В новых версиях Android и с библиотекой совместимости сохраненные фрагменты обычно являются лучшим способом обрабатывать данные, хранящие дорогостоящие данные для восстановления активности при уничтожении/создании активности. И, как указала Дайан, сохранение данных неконфигурации было для оптимизации таких вещей, как генерация миниатюр, которые сэкономить по соображениям производительности, но не критичны для функционирования вашей деятельности, если их нужно переделать - это не заменит правильное сохранение и восстановление состояния активности.

Но назад, когда я впервые ответил на это в 2010 году:
Если вы хотите сохранить свои собственные данные (состояние не просмотра), вы можете фактически передать произвольный объект специально для изменения ориентации с помощью onRetainNonConfigurationInstance(). См. это сообщение в блоге разработчиков Android. Просто будьте осторожны, чтобы не помещать какие-либо Представления или другие ссылки на предварительный поворот Контекста/Деятельности в передаваемом вами объекте, или вы предотвратите сбор этих мусора и, возможно, в конечном итоге исчерпаете память (это называется утечка контекста).

Ответ 2

Вы пытались использовать: его работу вокруг,

<activity name= ".YourActivity" android:configChanges="orientation|screenSize"/>

в файле манифеста?

Это не работает по умолчанию, потому что при изменении ориентации onCreate будет вызываться снова, и он перерисовывает ваше представление.

Если вы пишете этот параметр, вам не нужно обращаться в Activity, структура позаботится о остальном. При изменении ориентации он сохранит состояние экрана или макета.

ПРИМЕЧАНИЕ Если вы используете другой макет для ландшафтного режима, добавив эти параметры, макет для ландшафтного режима не будет вызываться.

Другой способ и Другой способ

Ответ 3

Во-первых, вам нужно определить, что на самом деле является "состоянием" в вашем приложении. Вы не сказали, что вы на самом деле делаете, но позвольте мне предположить, что объект ArrayList - это состояние, с которым пользователь работает.

Во-вторых, определите, каков жизненный цикл этого состояния на самом деле. Действительно ли это связано с этой деятельностью? Или пользователь должен не потерять его, если его батарея разрядится, устройство выключится, а потом вернется в ваше приложение? Если первый, onSaveInstanceState() правильный; если последний, вы хотите сохранить в постоянное хранилище в onPause().

Для onSaveInstanceState() с пользовательскими объектами ключ должен реализовать интерфейс Parcelable. Это включает в себя внедрение методов на Parcelable, а также создание статического объекта CREATOR в вашем классе. Здесь код типичного простого класса Parcelable:

https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/content/ComponentName.java

Ключевыми функциями являются реализация Parcelable:

https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/content/ComponentName.java#317

и статический класс CREATOR:

https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/content/ComponentName.java#355

(Статические writeToParcel() и readFromParcel() - это просто удобства, которые были сделаны для этого класса и не требуются.)

Теперь, когда у вас есть это, вы можете поместить весь свой массив ArrayList в сэкономленное состояние Bundle с помощью Bundle.putParcelableArrayList:

http://developer.android.com/reference/android/os/Bundle.html#putParcelableArrayList (java.lang.String, java.util.ArrayList)

В Activity.onCreate(), проверьте, есть ли у вас savedState Bundle, и если да, попробуйте извлечь ArrayList из него и использовать его, если он найден, создав новый адаптер и представление списка для нового действия, которое используется для отобразите его.

Ответ 4

но я заметил, что вы не можете помещать произвольные объекты в пакет!

Сначала создайте свои пользовательские объекты Parcelable.
Затем вы можете поместить их в пакет.

Все находится в ArrayList этих объектов

Вы можете использовать метод putParcelableArrayList в пакете для хранения массива ArrayList с настраиваемыми "разборчивыми" объектами.

Ответ 5

напишите свои объекты в JSON Strings, используя Google Gson, затем сохраните их как строку. Затем верните их из сохраненных строк JSON при восстановлении Activity/Fragment

import com.google.gson.Gson;

public class MyClass {
    private int a;
    private String s;
    private OtherSerializableClass other;
    private List<String> list;

    public String toJson() {
        return new Gson().toJson(this);
    }

    public static ChatAPI_MessagesArray fromJson(String json){
       return new Gson().fromJson(json, YourClass.class);
    }

    // Getters
    ...

    // Setters
    ...
}

Ответ 6

Для простых данных действие может использовать метод onSaveInstanceState() и восстанавливать его данные из пакета в onCreate(), но этот подход подходит только для небольших объемов данных, которые можно сериализовать, а затем десериализовать, но не для потенциально больших объемов данных. как список пользователей или растровые изображения.

The ViewModel class allows data to survive configuration changes such as screen rotations.
Architecture Components provides ViewModel helper class for the UI controller that is responsible for preparing data for the UI.

**Example**:

если вам нужно отобразить список пользователей в вашем приложении, убедитесь, что вы возложили ответственность за приобретение и ведение списка пользователей на ViewModel вместо действия или фрагмента, как показано в следующем примере кода.

public class MyViewModel extends ViewModel {
    private MutableLiveData<List<User>> users;
    public LiveData<List<User>> getUsers() {
        if (users == null) {
            users = new MutableLiveData<List<User>>();
            loadUsers();
        }
        return users;
    }

    private void loadUsers() {
        // Do an asynchronous operation to fetch users.
    }
}

public class MyActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
        // Create a ViewModel the first time the system calls an activity onCreate() method.
        // Re-created activities receive the same MyViewModel instance created by the first activity.

        MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
        model.getUsers().observe(this, users -> {
            // update UI
        });
    }
}