爪哇嵌套parcelable,不能初始化一个数组

问题描述 投票:1回答:2

好吧,我已经通过在堆栈溢出几乎每一个parcelable问题阅读,并试图以解决这个问题的一些解决方案。所以,总体来说,我有一个Android项目,我想通过ArrayList从一个类发送2个Intents阵列到另一个。

注意:这不是嵌套parcelable线程here不与阵列处理的副本。这不是this的副本,因为我已经做了一切嵌套类parcelable。这不是thisthis的副本,因为我没有使用一个数组列表,也是我认识到错误是初始化失败。因为我不需要在这种情况下一个参数的构造函数,是不是this的重复(我已经测试增加一个,并没有改变错误)。它也不是this的副本,因为它不是嵌套在一个包裹一个包裹。

我一定是因为如果我的阵列尚未初始化应该只出现空指针错误做一些明显。然而,它是不可能对我来说,我初始化数组的长度,直到我知道我要多久是...

(作为一个侧面说明也许有人可以给我更深入地了解readTypedList类正是XXX.Creator不会因为这无疑可能是问题的一部分,也可用于同样的问题here任何未来的人是对Parcel的javadoc这是一个链接言之有物,但并没有解决我的问题。)

所以,现在我有一个Display对象。显示对象仅用于存储String[]并允许它被瓜分。随打破了线已经低于评价,并应与包裹经验的人是显而易见的,因为它显然没有被初始化:

class Display implements Parcelable {

    String[] labels;

    public Display(String[] labels) {
        this.labels = labels;
    }

    protected Display(Parcel in) {
        in.readStringArray(this.labels); // **** THIS LINE BREAKS
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeStringArray(this.labels);
    }

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

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

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

所以,现在我问自己,我能做些什么来解决这个问题,并研究其他许多线程有希望的名字,但他们并没有解决我的问题。

Here是一个答案,我将不得不虽然会有所帮助,同样here他们建议使用createTypedList()readTypedList()代替。

不过,我想第一个答案,也this,他们没有工作,因为我事先没有想多久,我String[]是,刚刚结束了,而不是导致糟糕的数组长度错误认识做。而第二个答案没有帮助,因为显然我不希望创建一个新的类型化的列表,而是使用类型列表我已经有了,所以通过创建一个新的列表我结束了一个空的列表上失去我的数据。

所有这些问题的根源是,我的包裹被嵌套在另一个包内,并呼吁通过这样的事实:

in.readTypedList(allChartLabels, Display.CREATOR);

因为它嵌套,创建者是被称为以一种非常限制我的选择,并导致我无法解决问题。

纵观各种测试我也遇到了一些错误,但没有解决办法的......(当前的错误我的代码是扔是尝试获取空数组错误的长度)。


我知道有人有解决这一问题,并了解更多详情这里是我的代码的其余部分:

public class SummaryEntry implements Parcelable {

    private ArrayList<Calculation> allChartValues; // NOTE: this is another nested parcel class which is basically a duplicate of Display but with float[]
    private ArrayList<Display> allChartLabels;

    public SummaryEntry() {
        // initialize
        allChartValues = new ArrayList<>();
        allChartLabels = new ArrayList<>();
    }

    protected SummaryEntry(Parcel in) {
        this();

        // order in which we do this matters:
        in.readTypedList(allChartLabels, Display.CREATOR);
        in.readTypedList(allChartValues, Calculation.CREATOR);

    }

    @Override
    public void writeToParcel(Parcel out, int i) {
        // order in which we do this matters, must be same as reading typed lists
        out.writeTypedList(allChartLabels);
        out.writeTypedList(allChartValues);

    }

    /// ... getters and setters excluded because of irrelevance ///


    /// PARCELABLE METHODS

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

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

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

我很感谢你抽出时间来阅读这下长岗一路的时间。理想的情况是我要寻找一个解决String[]初始化问题,或者如果有人可以张贴他们的工作代码嵌套的包裹,包括阵列,或最后也许有人会指出一个简单的方法来实现通过这些项目,而不筑巢两幅。

java android android-intent parcelable
2个回答
1
投票

你可以像下面的代码:

使用writeArray&readArray是这样的:

试试下面更新的代码:

package com.myapplication;

import android.os.Parcel;
import android.os.Parcelable;

public class User implements Parcelable {

    String name;
    int age;
    String [] array;

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.name);
        dest.writeInt(this.age);
        dest.writeStringArray(this.array);
    }

    public User() {
    }

    protected User(Parcel in) {
        this.name = in.readString();
        this.age = in.readInt();
        this.array = in.createStringArray();
    }

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

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

0
投票

我仍然无法解决原来的问题的后半部分(这是如何包裹阵列),但我可以通过稍微重新设计我的计划成功实现了嵌套包裹实施。

新的设计打破了实现到4嵌套类有直接的实现。我也打消了我的阵列,因为我无法在包裹正确初始化它们。

编辑:我也偶然发现this website自动为您创建Parcelables并。非常有用的,我希望我之前就知道了!另外请注意,显然没有必要创建包裹类包裹StringFloat。您可以改为调用Float.class.getClassLoader()String.class.getClassLoader()使用包裹CREATORS这些类。

这里是我的代码:

Parcelable类Q含有的ArrayList的:

  • Parcelable类A,其包含字符串和浮标的2周的ArrayList

通过打破包裹成更小的嵌套包裹,我能够逐步测试包裹,直到我到达敲定解决方案,它能够经由这个代码我Intent传递:

在发送端:

    // create the parcel
    Q parcel = new Q();

    ArrayList<String> strings = new ArrayList<>();
    ArrayList<Float> stats = new ArrayList<>();

    // ... populate arraylists ... //

    Intent I = new Intent(CURRENTACTIVITY.this, FUTUREACTIVITY.class);
    // PUT THE THING
    I.putExtra("Data", parcel);

    startActivity(I);

在接收端:

    Q parcel = getIntent().getParcelableExtra("Data"); // get data

对于工作包裹全码:这个代码是很长,但重复设立包裹的基本原则是清晰和易于重复使用,如果你想创建自己的包裹。

// top level parcelable class Q
public class Q  implements Parcelable {

    private ArrayList<A> element;

    public Q()
    {
        this.element = new ArrayList<A>();
    }

    public void addToA(A a)
    {
        element.add(a);
    }

    public ArrayList<A> getA() {
        return element;
    }

    public void setA(ArrayList<A> a) {
        this.element = a;
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {

        dest.writeTypedList(this.element);

    }

    private Q (Parcel in){
        element = new ArrayList<A>();
        in.readTypedList(this.element, A.CREATOR);
    }

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

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

}

// nested parcel object A
public class A implements Parcelable {

    private ArrayList<Float> f;
    private ArrayList<String> s;

    public A() {
        f = new ArrayList<>();
        s = new ArrayList<>();
    }

    public A(ArrayList<Float> f, ArrayList<String> s) {
        this.f = f;
        this.s = s;
    }

    public ArrayList<String> getS() {
        return s;
    }

    public void setS(ArrayList<String> s) {
        this.s = s;
    }

    public ArrayList<Float> getF() {
        return f;
    }

    public void setF(ArrayList<Float>  f) {
        this.f = f;
    }


    protected A(Parcel in) {
        if (in.readByte() == 0x01) {
            f = new ArrayList<>();
            in.readList(f, Float.class.getClassLoader());
        } else {
            f = null;
        }
        if (in.readByte() == 0x01) {
            s = new ArrayList<>();
            in.readList(s, String.class.getClassLoader());
        } else {
            s = null;
        }
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        if (f == null) {
            dest.writeByte((byte) (0x00));
        } else {
            dest.writeByte((byte) (0x01));
            dest.writeList(f);
        }
        if (s == null) {
            dest.writeByte((byte) (0x00));
        } else {
            dest.writeByte((byte) (0x01));
            dest.writeList(s);
        }
    }

    @SuppressWarnings("unused")
    public static final Parcelable.Creator<A> CREATOR = new Parcelable.Creator<A>() {
        @Override
        public A createFromParcel(Parcel in) {
            return new A(in);
        }

        @Override
        public A[] newArray(int size) {
            return new A[size];
        }
    };
}
© www.soinside.com 2019 - 2024. All rights reserved.