代码之家  ›  专栏  ›  技术社区  ›  JFreeman Ian

Java嵌套PARCELLL,不能初始化数组

  •  1
  • JFreeman Ian  · 技术社区  · 5 年前

    好吧,我已经阅读了几乎每一个关于堆栈溢出的Parcelable问题,并尝试了许多解决方案来解决这个问题。所以总的来说,我有一个Android项目,我想发送2个 ArrayList 从一个类到另一个类的数组的s Intent .

    注意:这不是嵌套parcelable线程的副本 here 它不处理数组。它不是 this 因为我已经把所有的嵌套类都做成Parcelable。它不是 this this 因为我没有使用数组列表,而且我认识到错误是初始化失败。它不是 this 因为在这种情况下,我不需要无参数的构造函数(我已经测试了添加一个,它不会改变错误)。它也不是 this 因为它不是嵌套在包中的包。

    我必须做一些明显的事情,因为只有在数组未初始化时才会出现nullpointer错误。但是,在我知道数组的长度之前,不可能初始化它…

    (作为旁注,也许有人能让我更深入地了解 readTypedList 班级和具体内容 XXX.Creator 因为这无疑是问题的一部分。也适用于未来有同样问题的人 here 是指向 Parcel JavaDoc提供了大量信息,但没有解决我的问题。)

    现在我有了一个显示对象。显示对象仅用于存储 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 他们不工作,因为我不知道我要多久 字符串[ ] 最终导致了 数组长度错误 错误。第二个答案没有帮助,因为很明显我不想创建一个新的类型列表,而是使用我已有的类型列表,所以通过创建一个新列表,我最终得到一个空白列表,并丢失了我的数据。

    所有这些问题的根源是我的包嵌套在另一个包中并通过以下方式调用:

    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];
            }
        };
    }
    

    感谢你花时间阅读这篇长文章。理想情况下,我正在寻找解决方案 字符串[ ] 初始化问题,或者如果有人可以发布包含数组的嵌套包的工作代码,或者最后,也许有人可以指出一种更简单的方法来实现在不嵌套两个包的情况下传递这些项。

    2 回复  |  直到 5 年前
        1
  •  1
  •   Chetan Joshi weird    5 年前

    您可以按以下代码操作:

    使用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];
            }
        };
    }
    
        2
  •  0
  •   JFreeman Ian    5 年前

    我仍然无法解决最初问题的后半部分(即如何使用包数组),但是我可以通过稍微重新设计程序来成功实现嵌套包的实现。

    新的设计将实现分解为4个嵌套类,并直接实现。我还删除了数组,因为我无法在包中正确初始化它们。

    编辑:我也偶然发现 this website 它会自动为您创建Parcelables。非常有用,我希望我以前知道它! 另外请注意,显然不需要为包创建包类 String Float . 你可以打电话 Float.class.getClassLoader() String.class.getClassLoader() 为这些类使用包创建者。

    这是我的代码:

    Parcelable类Q 包含的数组列表:

    • Parcelable A级 其中包含2个字符串和浮点数组列表

    通过将包分解成更小的嵌套包,我可以逐步测试包,直到到达最终的解决方案,该解决方案能够通过 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];
            }
        };
    }