Intereting Posts
Как отобразить полноэкранное окно TYPE_SYSTEM_ALERT? Java.lang.ClassCastException: android.view.ViewGroup $ LayoutParams нельзя отбрасывать в android.widget.RelativeLayout $ LayoutParams Android: анимация анимации растрового изображения Изменение экранной ориентации Android для всех видов деятельности Обрезать видео с помощью FFMpeg очень медленно Как установить предварительный просмотр камеры в качестве фона для просмотра поверхности на экране rajawali & capture с помощью 3D Obj & Camera preview Размер спрайтов на разных размерах экрана Andengine Android Автоматическая всплывающая версия документации для Studio Studio Android, Как переименовать файл? Ориентация изображения от цели галереи / камеры Как я могу получить относительный путь к папкам в моем проекте Android? Обнаруживать обновление приложения Android и установить класс приложения boolean для отображения / скрытия EULA Примените много цветных фильтров к одному и тому же извлекаемому Кордова 4.3.0 Ошибка: установите Android-цель: «android-21» Добавить иконки в Android-навигатор?

Сохранение настраиваемого массива объектов в состоянии экземпляра

У меня есть List<CustomObject> (где CustomObject поступает из внешней библиотеки – я не могу вносить в него изменения). Я хочу сохранить это в onSaveInstanceState(Bundle) , но я не могу это сделать. Вот варианты, которые я пробовал:

 outState.putSerializable(KEY, (ArrayList<CustomObject>) myList); // because myList is instantiated as an ArrayList outState.putSerializable(KEY, myList.toArray()); 

Обе опции работают при переключении ориентации на телефоне (да, onSaveInstanceState вызывается при переключении ориентации – я проверил в logcat). Однако, когда текущая активность пытается запустить другую (с помощью startActivity(Intent) ), Android приостанавливает текущую активность и вызывает onSaveInstanceState() снова. На этот раз он не работает, по какой-то причине мне неизвестен. onSaveInstanceState() что onSaveInstanceState() успешно выполняется. Распечатка трассировки стека не указывает на мой код:

 E/AndroidRuntime(23898): java.lang.RuntimeException: Parcel: unable to marshal value my.custom.Object@5e07e43b E/AndroidRuntime(23898): at android.os.Parcel.writeValue(Parcel.java:1087) E/AndroidRuntime(23898): at android.os.Parcel.writeArray(Parcel.java:519) E/AndroidRuntime(23898): at android.os.Parcel.writeValue(Parcel.java:1072) E/AndroidRuntime(23898): at android.os.Parcel.writeMapInternal(Parcel.java:469) E/AndroidRuntime(23898): at android.os.Bundle.writeToParcel(Bundle.java:1445) E/AndroidRuntime(23898): at android.os.Parcel.writeBundle(Parcel.java:483) E/AndroidRuntime(23898): at android.app.ActivityManagerProxy.activityPaused(ActivityManagerNative.java:1427) E/AndroidRuntime(23898): at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:3106) E/AndroidRuntime(23898): at android.app.ActivityThread.access$2400(ActivityThread.java:119) E/AndroidRuntime(23898): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1870) E/AndroidRuntime(23898): at android.os.Handler.dispatchMessage(Handler.java:99) E/AndroidRuntime(23898): at android.os.Looper.loop(Looper.java:123) E/AndroidRuntime(23898): at android.app.ActivityThread.main(ActivityThread.java:4363) E/AndroidRuntime(23898): at java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime(23898): at java.lang.reflect.Method.invoke(Method.java:521) E/AndroidRuntime(23898): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) E/AndroidRuntime(23898): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) E/AndroidRuntime(23898): at dalvik.system.NativeStart.main(Native Method) 

Есть ли способ сохранить пользовательские объекты в состоянии экземпляра?

Solutions Collecting From Web of "Сохранение настраиваемого массива объектов в состоянии экземпляра"

Сделайте свой CustomObject реализованным Parcelable и используйте:

 outState.putParcelable(KEY, myList); onSaveInstanceState(outState); 

Также проверьте этот учебник.

EDIT после комментария CommonsWare:

Если ваш CustomObject не реализует Serializable или Parcelable я бы попытался обернуть его внутри собственного объекта и добавить:

  • private void readObject(ObjectInputStream aStream) throws IOException, ClassNotFoundException { /*Your deserialization */ }
  • private void writeObject(ObjectOutputStream aStream) throws IOException { /*Your serialization */}

List<CustomObject> свой List<CustomObject> службой и сделайте ее доступной для ваших действий через локальный шаблон привязки.

Вам не только не нужно беспокоиться о том, чтобы удерживать его в вашем состоянии экземпляра, но вы немного лучше контролируете время жизни этих объектов в памяти. Время жизни экземпляра контролируется Android; Как долго Service держится на объектах, контролируется вами. В частности, если CustomObject может быть большим, или список может быть длинным, я бы предпочел, чтобы у вас был больший контроль над тем, сколько времени потребляется ОЗУ.

Если это прежде всего для обработки изменений ориентации, может ли Activity#onRetainNonConfigurationInstance() делать то, что вы хотите?

Активность может использовать этот API для распространения расширенного состояния от старого к новому экземпляру активности, от загруженных растровых изображений, до сетевых подключений, до равномерного активного выполнения потоков. Обратите внимание, что вам не следует распространять данные, которые могут меняться в зависимости от конфигурации, включая любые данные, загружаемые из таких ресурсов, как строки, макеты или чертежи.

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

Насколько мне известно, SavedInstanceState предназначен для сохранения пользовательской конфигурации активности (например, стандартные виджеты пользовательского интерфейса Android, например текстовое поле, автоматически сохраняются).

Если вы хотите сохранить пользовательский объект между различными перезагрузками активности (это не относится к завершению деятельности, инициированной пользователем, нажав кнопку «Назад», но применяется, например, для изменения ориентации). Используйте следующий код для сохранения объекта:

 // maintain a reference to the EchoServer object when the activity is recreated @Override public Object onRetainNonConfigurationInstance() { return <<your object of choice>>; } 

И в методе onCreate (Bundle savedInstanceState) вы можете восстановить объект:

  // if there is a saved instance state, restore the state if (savedInstanceState != null) { <<yourObject>> = (<<your object's class) getLastNonConfigurationInstance(); 

Почему бы просто не сохранить объект на SD-карту? Вы можете увидеть пример того, как я использую это в своем блоге >> http://androidworkz.com/2010/07/06/source-code-imageview-flipper-sd-card-scanner/

 public void saveArray(String filename, String[] output_field) { try { FileOutputStream fos = new FileOutputStream(filename); GZIPOutputStream gzos = new GZIPOutputStream(fos); ObjectOutputStream out = new ObjectOutputStream(gzos); out.writeObject(output_field); out.flush(); out.close(); } catch (IOException e) { e.getStackTrace(); } } public String[] loadArray(String filename) { try { FileInputStream fis = new FileInputStream(filename); GZIPInputStream gzis = new GZIPInputStream(fis); ObjectInputStream in = new ObjectInputStream(gzis); String[] read_field = (String[])in.readObject(); in.close(); return read_field; } catch (Exception e) { e.getStackTrace(); } return null; }