2016-06-24 10 views
0

Как написать Parcelable для дерева, как структура, которая имеет Base класс с двумя реализациями, один в Node типа, а другой Container типа, который содержит список Base типов.Android Parcelable с деревом родовых типов

Извините за массу кода, приведенного ниже. Основная структура данных небольшая, но в нее включена моя текущая реализация Parcelable, которая не работает.

Я попытался добавить байт в базу writeToParcel, который сигнализирует, какой тип создавать, когда он отделяется, но, похоже, не работает.

Проблема в том, что я получаю разные данные обратно при отправке объекта Base, который содержит глубокое дерево Container объектов.

Любые идеи о том, что я делаю неправильно?

Также будут оценены любые идеи о том, как реализовать модульные тесты для Parcelable.

Базовый класс

public abstract class Base implements Parcelable { 
    public int val; 
    protected Base(final int val) { 
     this.val = val; 
    } 


    @Override 
    public int describeContents() { 
     return 0; 
    } 

    @Override 
    public void writeToParcel(Parcel dest, int flags) { 
     dest.writeByte((byte) (this instanceof NodeBase ? 0 : 1)); 
     dest.writeInt(this.val); 
    } 

    protected Base(Parcel in) { 
     this.val = in.readInt(); 
    } 

    public static final Creator<Base> CREATOR = new Creator<Base>() { 
     @Override 
     public Base createFromParcel(Parcel source) { 
      return source.readByte() == 0 ? new NodeBase(source) : new ContainerBase(source); 
     } 

     @Override 
     public Base[] newArray(int size) { 
      return new Base[size]; 
     } 
    }; 
} 

Node Class

public class NodeBase extends Base { 

    public final String name; 

    public NodeBase(final int val, final String name) { 
     super(val); 
     this.name = name; 
    } 

    @Override 
    public int describeContents() { 
     return 0; 
    } 

    @Override 
    public void writeToParcel(Parcel dest, int flags) { 
     super.writeToParcel(dest, flags); 
     dest.writeString(this.name); 
    } 

    protected NodeBase(Parcel in) { 
     super(in); 
     this.name = in.readString(); 
    } 

    public static final Creator<NodeBase> CREATOR = new Creator<NodeBase>() { 
     @Override 
     public NodeBase createFromParcel(Parcel source) { 
      return new NodeBase(source); 
     } 

     @Override 
     public NodeBase[] newArray(int size) { 
      return new NodeBase[size]; 
     } 
    }; 
} 

Контейнер класса

public class ContainerBase extends Base { 
    public final List<Base> baseList; 

    public ContainerBase(final int val, final List<Base> baseList) { 
     super(val); 
     this.baseList = baseList; 
    } 

    @Override 
    public int describeContents() { 
     return 0; 
    } 

    @Override 
    public void writeToParcel(Parcel dest, int flags) { 
     super.writeToParcel(dest, flags); 
     dest.writeTypedList(this.baseList); 
     dest.writeInt(this.val); 
    } 

    protected ContainerBase(Parcel in) { 
     super(in); 
     this.baseList = in.createTypedArrayList(Base.CREATOR); 
     this.val = in.readInt(); 
    } 

    public static final Creator<ContainerBase> CREATOR = new Creator<ContainerBase>() { 
     @Override 
     public ContainerBase createFromParcel(Parcel source) { 
      return new ContainerBase(source); 
     } 

     @Override 
     public ContainerBase[] newArray(int size) { 
      return new ContainerBase[size]; 
     } 
    }; 
} 

ответ

0

Вы упомянули Общие типы, но я не вижу никаких общих типов, используемых в вашем коде. Все, что я вижу, это унаследованные классы родительского и дочернего. Но если предположить, что ваш узел и Container являются универсальными и что они имеют общий параметр T, где T может быть любой объект, который может храниться в вашем узле/контейнер, то следующее решение должно помочь:

Шаг 1. Храните классы, которая простирается от ваших родовых классов в виде строки в вашем базовом классе:

public abstract class Base implements Parcelable { 
    private String containerClassName; 
    private String nodeClassName; 

Шаг 2. Убедитесь, что ваши общие классы называют super(), которые вы уже сделали.

Этап 3. Любые классы, которые простираются от ваших общих классов необходимы указать имя класса во время его строительства, как это:

public class NewNode extends NodeBase { 

    public NodeBase() { 
     super(); 
     setClassNames(NewNode.class.getName()); // Base class setter method 
    } 

Шаг 4. В своем базовом классе вы можете читать/писать имена классов для getClassLoader() следующим образом:

protected NodeBase(Parcel in) { 
    super(in); 
    this.containerClassName = in.readString(); 
    this.nodeClassName = in.readString(); 

    ClassLoader containerLoader; 
    ClassLoader nodeLoader; 
    try { 
     containerLoader = Class.forName(containerClassName).getClassLoader(); 
     nodeLoader = Class.forName(nodeClassName).getClassLoader(); 
    } catch (ClassNotFoundException e) { 
     e.printStackTrace(); 
    } 
    containerObject = in.readParcelable(containerLoader); 
    nodeObject = in.readParcelable(nodeLoader); 
    //... Other class members can go here 
} 

@Override 
public void writeToParcel(Parcel dest, int flags) { 
    super.writeToParcel(dest, flags); 
    dest.writeString(containerClassName); 
    dest.writeString(nodeClassName); 
    //... Other class members can go here 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^