2012-09-19 25 views
48

Mam ArrayList z obiektami niestandardowymi, które chciałbym móc zapisać i przywrócić na obrót ekranu.Jak zapisać niestandardową tablicę ArrayList na ekranie Android obracać?

Wiem, że można to zrobić z onSaveInstanceState i onRestoreInstanceState gdybym aby ArrayList własną klasę, która implementuje zarówno Parcelable lub Serializable ... Ale czy jest jakiś sposób, aby to zrobić bez tworzenia innej klasy?

Odpowiedz

81

Nie trzeba tworzyć nowej klasy, aby przekazać ArrayList swoich niestandardowych obiektów. Powinieneś po prostu zaimplementować klasę Parcelable dla swojego obiektu i użyć Bundle#putParcelableArrayList() w onSaveInstanceState() i onRestoreInstanceState(). Ta metoda sama zachowa ArrayList of Parcelables.


Ponieważ przedmiotem Parcelables (i Serializables i zestawy) czasami sprawia, że ​​mój ból głowy, tutaj jest podstawowym przykładem ArrayList zawierającej zwyczaj Parcelable obiektów przechowywanych w wiązce. (To jest cięty & pasta runnable, nie układ niezbędny.)

wykonawcze Parcelable

public class MyObject implements Parcelable { 
    String color; 
    String number; 

    public MyObject(String number, String color) { 
     this.color = color; 
     this.number = number; 
    } 

    private MyObject(Parcel in) { 
     color = in.readString(); 
     number = in.readString(); 
    } 

    public int describeContents() { 
     return 0; 
    } 

    @Override 
    public String toString() { 
     return number + ": " + color; 
    } 

    public void writeToParcel(Parcel out, int flags) { 
     out.writeString(color); 
     out.writeString(number); 
    } 

    public static final Parcelable.Creator<MyObject> CREATOR = new Parcelable.Creator<MyObject>() { 
     public MyObject createFromParcel(Parcel in) { 
      return new MyObject(in); 
     } 

     public MyObject[] newArray(int size) { 
      return new MyObject[size]; 
     } 
    }; 
} 

Save/Restore członkowskie

public class Example extends ListActivity { 
    ArrayList<MyObject> list; 

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

     if(savedInstanceState == null || !savedInstanceState.containsKey("key")) { 
      String[] colors = {"black", "red", "orange", "cyan", "green", "yellow", "blue", "purple", "magenta", "white"}; 
      String[] numbers = {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"}; 

      list = new ArrayList<MyObject>(); 
      for(int i = 0; i < numbers.length; i++) 
       list.add(new MyObject(numbers[i], colors[i])); 
     } 
     else { 
      list = savedInstanceState.getParcelableArrayList("key"); 
     } 

     setListAdapter(new ArrayAdapter<MyObject>(this, android.R.layout.simple_list_item_1, list)); 
    } 

    @Override 
    protected void onSaveInstanceState(Bundle outState) { 
     outState.putParcelableArrayList("key", list); 
     super.onSaveInstanceState(outState); 
    } 
} 
+1

Dzięki! Jednak jestem zagubiony na 'private MyObject (Parcel in) { color = in.readString(); number = in.readString(); } 'bit ... To jest łatwe dla Strings, ale jak mogę odczytać moją własną listę tablic? 'in.readArrayList (MyObject.class.getClassLoader())' daje mi błąd. – Kalina

+1

Hmm, w pytaniu pytałeś o "ArrayList z niestandardowymi obiektami", co oznacza "ArrayList ", którą ta odpowiedź obsługuje w 'Parcelable.Creator'; jednak twój komentarz po prostu zapytał "jak mogę odczytać moją własną listę tablic", co oznacza "MyArrayList". Jakiej klasy starasz się przedłużyć? (Przepraszam za techniczne, ale chcę dać ci najlepszą odpowiedź najszybciej.) – Sam

+0

Przepraszam, mam na myśli ArrayList Kalina

3

Można użyć onRetainNonConfigurationInstance(). Pozwala na zapisanie dowolnego obiektu przed zmianą konfiguracji i przywrócenie go po getLastNonConfigurationInstanceState().

Wewnątrz działalności:

@Override 
    public Object onRetainNonConfigurationInstance() { 
     return myArrayList; 
    } 

Wewnątrz onCreate():

try{ 
     ArrayList myArrayList = (ArrayList)getLastNonConfigurationInstance(); 
    } catch(NullPointerException e) {} 

Handling Runtime Changes: http://developer.android.com/guide/topics/resources/runtime-changes.html Dokumentacja: http://developer.android.com/reference/android/app/Activity.html#onRetainNonConfigurationInstance%28%29

+0

Wow, nigdy nie wiedziałem o tej funkcji! Super proste i dokładnie to, czego potrzebowałem ... Jednak widzę, że jest przestarzałe ... – Kalina

+0

Niestety, ale nadal działa i nie ma innego prostego sposobu na zrobienie tego. Odpowiedź Sama jest jedynym innym sposobem, jaki znalazłem, ale trudniej go wdrożyć. – Techwolf

+3

Jeśli używasz Fragmentów, możesz użyć 'Fragment.setRetainInstance (true)', który jest nowszą wersją tego (ale działa tylko z Fragmentami). Dokumentacja: http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean) – Techwolf

-2

Tak, można zapisać kompozytowego obiekt we wspólnych upodobań. Powiedzmy:

Student mStudentObject = new Student(); 
    SharedPreferences appSharedPrefs = PreferenceManager 
     .getDefaultSharedPreferences(this.getApplicationContext()); 
     Editor prefsEditor = appSharedPrefs.edit(); 
     Gson gson = new Gson(); 
     String json = gson.toJson(mStudentObject); 
     prefsEditor.putString("MyObject", json); 
     prefsEditor.commit(); 

a teraz można odzyskać przedmiot:

 SharedPreferences appSharedPrefs = PreferenceManager 
    .getDefaultSharedPreferences(this.getApplicationContext()); 
    Editor prefsEditor = appSharedPrefs.edit(); 
    Gson gson = new Gson(); 
    String json = appSharedPrefs.getString("MyObject", ""); 
    Student mStudentObject = gson.fromJson(json, Student.class); 
+1

Zły pomysł, aby to zrobić - w zależności od rozmiar zapisywanej listy. SharedPreferences jest plikiem XML, nie jest przeznaczony do przechowywania ogromnych zestawów danych. – mwieczorek