2013-08-11 16 views
8

piuttosto semplice scenario davvero, ma non sono riuscito a trovare tutto ciò che riguarda il Google quindi ecco qui:Parcelable Android riferimento a un'altra dipendenza circolare Parcelable

class ContainerClass implements Parcelable { 
    List<ItemClass> _items; 
    (...) 

    public void writeToParcel(Parcel p, int args) { 
    p.writeList(_items); 
    (...) 
    } 
} 

class ItemClass implements Parcelable { 
    ContainerClass _containerRef;  
    (...) 

    public void writeToParcel(Parcel p, int args) { 
    p.writeParcelable(_containerRef); 
    (...) 
    }  
} 

Questo inevitabilmente ciclo e overflow dello stack.

La mia domanda: come posso gestire una situazione in cui devo passare un oggetto dei tipi sopra riportati a una nuova attività.

(per CommonsWare) L'implementazione parcellare sembra non controllare ed evitare dipendenze circolari. Stacktrace con classnames sostituiti con nomi di cui sopra:

08-12 10:17:45.233 5590-5590/com.package E/AndroidRuntime: FATAL EXCEPTION: main 
     java.lang.StackOverflowError 
     at com.package.ContainerClass.writeToParcel(ContainerClass.java:139) 
     at android.os.Parcel.writeParcelable(Parcel.java:1254) 
     at com.package.ItemClass.writeToParcel(ItemClass.java:182) 
     at android.os.Parcel.writeParcelable(Parcel.java:1254) 
     at android.os.Parcel.writeValue(Parcel.java:1173) 
     at android.os.Parcel.writeList(Parcel.java:622) 
     at com.package.ContainerClass.writeToParcel(ContainerClass.java:144) 
     at android.os.Parcel.writeParcelable(Parcel.java:1254) 
     at com.package.ItemClass.writeToParcel(ItemClass.java:182) 
     at android.os.Parcel.writeParcelable(Parcel.java:1254) 
     at android.os.Parcel.writeValue(Parcel.java:1173) 
     at android.os.Parcel.writeList(Parcel.java:622) 

risposta

1

ho riflettuto un po 'di più e venire con due soluzioni utili se qualcun altro è nella stessa barca:

1) (Ispirato CommonsWare) mettere una bandierina su ogni parte della catena per indicare direction L'heirarchy è in perdita nel senso che non è possibile ripristinare tutti gli elementi della ContainerClass.

class ContainerClass implements Parcelable { 
    boolean _parcelableDownHeirarchy = true; 
    List<ItemClass> _items; 
    (...) 

    private ContainerClass(Parcel in) { 
    _items = in.readArrayList(ItemClass.class.getClassLoader()); 
    (...) 

    if (_parcelableDownHierarchy) { 
     for (int i = 0; i < _items.size(); i++) 
     _items.get(i).set_container(this); 
    }   
    } 

    public void writeToParcel(Parcel p, int args) { 
    p.writeByte((byte)_parcelableDownHierarchy ? 1 : 0); 
    if (_parcelableDownHeirarchy) 
     p.writeList(_items); 

    (...) 
    } 
} 


class ItemClass implements Parcelable { 
    boolean _parcelableDownHeirarchy = true; 
    ContainerClass _containerRef;  
    (...) 

    private ItemClass(Parcel in) { 
    if (!_parcelableDownHeirarchy) { 
     _containerRef = in.readParcelable(ContainerClass.class.getClassLoader()); 
     //Won't contain item in it's _items list.   
    } 
    } 

    public void writeToParcel(Parcel p, int args) { 
    p.writeByte((byte)_parcelableDownHierarchy ? 1 : 0); 
    if (!_parcelableDownHeirarchy) //Up the heirarchy 
     p.writeParcelable(_containerRef); 

    (...) 
    }  
} 

2) soluzione Hackish, impiegando una tabella hash statico, concesso ogni oggetto può essere identificato in modo univoco da esso è attributi Parcelable. (Nel mio caso ho la chiave primaria nel mio database negli oggetti).

class ContainerClass implements Parcelable { 
    //Leave be 
} 


class ItemClass implements Parcelable { 
    HaspMap<Long, ContainerClass> _parents = new HashMap<Long, ContainerClass>(); 
    ContainerClass _containerRef;  
    (...) 

    public long get_PKhash() { /* Return unique identifier */ } 

    private ItemClass(Parcel in) { 
    (...) 
    assertTrue((_containerRef = _parents.remove(get_PKhash())) != null); 
    } 

    public void writeToParcel(Parcel p, int args) { 
    (...)//Don't write _containerRef 
    _parents.put(this.get_PKhash, _containerRef); 
    }  
} 
+0

Ho finito per implementare il numero 2. – Skod

8

Questo inevitabilmente ciclo e overflow dello stack.

AFAIK, la procedura di parceling non gestisce circular object graphs. Ho appena archiviato an issue to get this better documented.

Una soluzione alternativa è di non eseguire p.writeParcelable(_containerRef);. Invece, nel tuo , nel tuo costruttore ContainerClass(Parcel in) (o comunque il tuo lo sta gestendo), dopo aver letto nel tuo elenco _items, scorrere su quell'elenco e dire a ogni bambino del suo genitore.

+0

Questa soluzione sarebbe ottima se dovessi passare a ContainerClass. Sfortunatamente è una raccolta di istanze di ItemClass che devo passare a un'attività. Mentre potrei fare il contrario e non p.writeList in quanto non ho davvero bisogno di quelle informazioni in questa parte del mio programma, quell'implementazione causa problemi in altre parti quando le istanze ContainerClass "Parseled" non avranno gli _items. – Skod

+0

Questa soluzione funziona per me. – kdroider

Problemi correlati