Android Parcelable与通用类型的树

时间:2016-06-24 23:47:34

标签: java android inheritance parcelable parcel

如何为类似于Parcelable类的结构编写Base,其中Node类包含两个实现,一个为Container类型,另一个为Base类型包含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]; } }; } 对象时,我得到了不同的数据。

关于我做错的任何想法?

此外,任何关于如何为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];
        }
    };
}

节点类

import React from "react";
import darkBaseTheme from 'material-ui/styles/baseThemes/darkBaseTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import Avatar from 'material-ui/Avatar';
import AccountCircle from 'material-ui/svg-icons/action/account-circle';
import ContentAdd from 'material-ui/svg-icons/content/add';
import FloatingActionButton from 'material-ui/FloatingActionButton';
import {List, ListItem} from 'material-ui/List';
import IconButton from 'material-ui/IconButton';

export default class Inbox extends React.Component {
  constructor() {
    super();
  }

  _test() {
    alert("_test");
  }

  render() {
    let that = this;

    // const iconButtonElement = (
    //   <button onClick={that._test}></button>
    // );

    const iconButtonElement = (
      <FloatingActionButton mini={true} onMouseDown={ that._test }>
        <ContentAdd />
      </FloatingActionButton>
    );

    return (
      <div className="darkContainer">
        <div className="containerBanner">

          <MuiThemeProvider muiTheme={getMuiTheme(darkBaseTheme)}>

            <div className="column5">
              { iconButtonElement }

              <br></br>

              <List>

                <ListItem
                  leftAvatar={<Avatar icon={ <AccountCircle /> } />}
                  rightIconButton={iconButtonElement}
                  primaryText="Jon Doe"
                  onTouchTap={that._test}
                />

              </List>

            </div>
          </MuiThemeProvider>

        </div>
      </div>
    );
  }
}

容器类

$(document).ready(function() {
    $.getJSON('scripts/json/articles.json', function(data) {
        $.each(data, function(i) {
            parent = $("<div class='card'/>");
            a = $("<a href=" + data['articles']['0'].Link + " target='_target'/>")
            li = $("<li class='bottom-description'/>");

            parent.append(a);

            a.append("<img src=" + data['articles']['0'].Image + "/>");
            a.append(li);

            li.append("<p class='title'>" + data['articles']['0'].Title + "</p>");
            li.append("<h3 class='desc'>" + data['articles']['0'].Description + "</h3>");
            $('.card-section').append(parent);
        })
    });
})

1 个答案:

答案 0 :(得分:0)

您提到了通用类型,但我没有看到您的代码中使用了任何通用类型。我看到的只是Parent和Child继承的类。但假设您的Node和Container是通用的并且它们具有通用参数 T ,其中T可以是可以存储在您的Node / Container中的任何对象,那么以下解决方案应该有所帮助:

第1步。将从Generic类扩展的类作为字符串存储在基类中:

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
}