java - 可包裹物体的循环引用

标签 java android arraylist parcelable

我已经搜索了很多有关ArrayList类型的传递对象的信息,但没有找到解决我的问题的有用方法。这就是问题:

我有一个Vertex类(实现了Parcelable),它具有4个属性:名称(字符串),minDistance(双精度),上一个(顶点)和邻接的ArrayList(边的ArrayList)。

我还有一个Edge类(实现了Parcelable),它具有3种属性:from(Vertex),target(Vertex)和weight(double)。

在我的MainActivity中,我获得了一个顶点的ArrayList(每个顶点都有一个Arrays of Edges),并且我想将ArrayList传递给另一个 Activity 。此刻,我遇到了StackOverflowError。

类Vertex.java

   public class Vertex implements Comparable<Vertex>, Parcelable {
    public final String name;
    public List<Edge> adjacencies = new ArrayList<Edge>();
    public double minDistance = Double.POSITIVE_INFINITY;
    public Vertex previous;

    public Vertex(String argName) {
        name = argName;
    }

    public Vertex(Parcel in) {
        this.name = in.readString();
        this.minDistance=in.readDouble();
        Object[]aristas= in.readArray(Edge.class.getClassLoader());
        setAdjacencies(aristas);
    }

    public void addEdge(Edge e) {
        adjacencies.add(e);
    }

    public String toString() {
        return name;
    }

    public int compareTo(Vertex other) {
        return Double.compare(minDistance, other.minDistance);
    }

    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        // TODO Auto-generated method stub
        dest.writeString(name);
        dest.writeDouble(minDistance);     
        Object[] edgesArray = adjacencies.toArray();
        dest.writeArray(edgesArray);

    }

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

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

    public void setAdjacencies(Object[] edges) {
        for (Object edge : edges) {
            if (edge instanceof Edge) {
                adjacencies.add((Edge) edge);
            }
        }
    }

}

类Edge.java
   public class Edge implements Parcelable {

    private Vertex from;
    private Vertex target;
    private double weigth;

    public Edge(Vertex from, Vertex target, double weight) {
        this.target = target;
        this.weigth = weight;
        this.from = from;
    }

    public Edge(Parcel in) {
        this.weigth=in.readDouble();
        this.target=(Vertex) in.readParcelable(getClass().getClassLoader());
        this.from=(Vertex) in.readParcelable(getClass().getClassLoader());  
    }

    public Vertex getTarget() {
        return target;
    }

    public void setTarget(Vertex target) {
        this.target = target;
    }

    public double getWeigth() {
        return weigth;
    }

    public void setWeigth(double weigth) {
        this.weigth = weigth;
    }

    public Vertex getFrom() {
        return from;
    }

    public void setFrom(Vertex from) {
        this.from = from;
    }

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return getFrom().toString() + " -> " + weigth + " -> "
                + getTarget().toString();
    }

    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        // TODO Auto-generated method stub
        dest.writeDouble(weigth);
        dest.writeParcelable( target,flags);
        dest.writeParcelable(from, flags);

    }

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

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

}

非常感谢您的帮助

谢谢

我忘了展示发送和接收可打包对象的方式:

发送(Fragment.java):
i.putParcelableArrayListExtra("LIST_VERTEX", ((MainActivity)getActivity()).getListaVertex());

接收(ResultActivity.java):
nodos = getIntent().getParcelableArrayListExtra("LIST_VERTEX");

注意:(((MainActivity] getActivity())。getListaVertex()是顶点对象的ArrayList

LOGCAT:

11-23 01:52:25.384:E / AndroidRuntime(21939):致命异常:主
11-23 01:52:25.384:E / AndroidRuntime(21939):java.lang.StackOverflowError
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeString(Parcel.java:513)
11-23 01:52:25.384:E / AndroidRuntime(21939):at com.csacanam.dijkstra.Vertex.writeToParcel(Vertex.java:56)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):在com.csacanam.dijkstra.EdgesList.writeToParcel(EdgesList.java:48)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):at com.csacanam.dijkstra.Vertex.writeToParcel(Vertex.java:58)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):在com.csacanam.dijkstra.EdgesList.writeToParcel(EdgesList.java:48)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):at com.csacanam.dijkstra.Vertex.writeToParcel(Vertex.java:58)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):在com.csacanam.dijkstra.EdgesList.writeToParcel(EdgesList.java:48)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):at com.csacanam.dijkstra.Vertex.writeToParcel(Vertex.java:58)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):在com.csacanam.dijkstra.EdgesList.writeToParcel(EdgesList.java:48)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):at com.csacanam.dijkstra.Vertex.writeToParcel(Vertex.java:58)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):在com.csacanam.dijkstra.EdgesList.writeToParcel(EdgesList.java:48)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):at com.csacanam.dijkstra.Vertex.writeToParcel(Vertex.java:58)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):在com.csacanam.dijkstra.EdgesList.writeToParcel(EdgesList.java:48)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):at com.csacanam.dijkstra.Vertex.writeToParcel(Vertex.java:58)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):在com.csacanam.dijkstra.EdgesList.writeToParcel(EdgesList.java:48)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):at com.csacanam.dijkstra.Vertex.writeToParcel(Vertex.java:58)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):在com.csacanam.dijkstra.EdgesList.writeToParcel(EdgesList.java:48)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):at com.csacanam.dijkstra.Vertex.writeToParcel(Vertex.java:58)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):在com.csacanam.dijkstra.EdgesList.writeToParcel(EdgesList.java:48)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):at com.csacanam.dijkstra.Vertex.writeToParcel(Vertex.java:58)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):在com.csacanam.dijkstra.EdgesList.writeToParcel(EdgesList.java:48)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):at com.csacanam.dijkstra.Vertex.writeToParcel(Vertex.java:58)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):在com.csacanam.dijkstra.EdgesList.writeToParcel(EdgesList.java:48)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):at com.csacanam.dijkstra.Vertex.writeToParcel(Vertex.java:58)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):在com.csacanam.dijkstra.EdgesList.writeToParcel(EdgesList.java:48)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):at com.csacanam.dijkstra.Vertex.writeToParcel(Vertex.java:58)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):在com.csacanam.dijkstra.EdgesList.writeToParcel(EdgesList.java:48)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):at com.csacanam.dijkstra.Vertex.writeToParcel(Vertex.java:58)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):在com.csacanam.dijkstra.EdgesList.writeToParcel(EdgesList.java:48)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):at com.csacanam.dijkstra.Vertex.writeToParcel(Vertex.java:58)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):在com.csacanam.dijkstra.EdgesList.writeToParcel(EdgesList.java:48)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):at com.csacanam.dijkstra.Vertex.writeToParcel(Vertex.java:58)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):在com.csacanam.dijkstra.EdgesList.writeToParcel(EdgesList.java:48)
11-23 01:52:25.384:E / AndroidRuntime(21939):位于android.os.Parcel.writeParcelable(Parcel.java:1254)
11-23 01:52:25.384:E / AndroidRuntime(21939):在com.csacanam.dijkstra.Vertex.writeToParcel(Vertex

编辑:

此解决方法解决了我的循环引用问题

新边缘类:
public class Edge implements Parcelable {

    public String PKhash;
    private Vertex from;
    private Vertex target;
    private double weigth;

    public static HashMap<String, Vertex> _parentsFrom = new HashMap<String, Vertex>();
    public static HashMap<String, Vertex> _parentsTarget = new HashMap<String, Vertex>();

    public String get_PKhash() {
        /* Return a unique identifier of your Edge object here */
        return PKhash;
    }

    public Edge(Vertex from, Vertex target, double weight) {
        this.target = target;
        this.weigth = weight;
        this.from = from;
        this.PKhash=from.name+","+getWeigth()+","+target.name;
    }

    public Edge( Parcel in ) {
        this.weigth = in.readDouble();
        this.PKhash  = in.readString();
        Assert.assertTrue( (from = _parentsFrom.get( this.PKhash )) != null );
        Assert.assertTrue( (target = _parentsTarget.get( this.PKhash )) != null );
    }


    public Vertex getTarget() {
        return target;
    }

    public void setTarget(Vertex target) {
        this.target = target;
    }

    public double getWeigth() {
        return weigth;
    }

    public void setWeigth(double weigth) {
        this.weigth = weigth;
    }

    public Vertex getFrom() {
        return from;
    }

    public void setFrom(Vertex from) {
        this.from = from;
    }

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return getFrom().toString() + " -> " + weigth + " -> "
                + getTarget().toString();
    }

    @Override
    public int describeContents() {
        // TODO Auto-generated method stubz
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        // TODO Auto-generated method stub
        dest.writeDouble(weigth);
        this.PKhash="";
        this.PKhash=from.name+","+getWeigth()+","+target.name;
        dest.writeString(PKhash);
        _parentsFrom.put(PKhash, from);
        _parentsTarget.put( PKhash, target);

    }

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

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


}

新顶点类
public class Vertex implements Comparable<Vertex>, Parcelable {
    public final String name;
    public List<Edge> adjacencies = new ArrayList<Edge>();
    public double minDistance = Double.POSITIVE_INFINITY;
    public Vertex previous;

    public Vertex(String argName) {
        name = argName;
    }

    public Vertex(Parcel in) {
        this.name = in.readString();
        this.minDistance=in.readDouble();
        Object[]aristas= in.readArray(Edge.class.getClassLoader());
        setAdjacencies(aristas);
    }

    public void addEdge(Edge e) {
        adjacencies.add(e);
    }

    public String toString() {
        return name;
    }

    public int compareTo(Vertex other) {
        return Double.compare(minDistance, other.minDistance);
    }

    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        // TODO Auto-generated method stub
        dest.writeString(name);
        dest.writeDouble(minDistance);     
        Object[] edgesArray = adjacencies.toArray();
        dest.writeArray(edgesArray);

    }

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

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

    public void setAdjacencies(Object[] edges) {
        for (Object edge : edges) {
            if (edge instanceof Edge) {
                adjacencies.add((Edge) edge);
            }
        }
    }

    @Override
    public int hashCode() {
        // TODO Auto-generated method stub
        return name.hashCode();
    }

}

最佳答案

您无需在Parcelable中实现EdgeList。实际上,据我了解,您根本不需要EdgeList。只需按如下所示修改Vertex类:

public List<Edge> adjacencies = new ArrayList<Edge>();

public Edge(Parcel in) {
    name = in.getString();
    minDistance = in.getDouble();
    adjancencies = in.readParcelableArray(Edge.getClass().getClassLoader()); 
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(name);
    dest.writeDouble(minDistance);
    pc.writeParcelableArray((ArrayList<? extends Parcelable>) adjacencies, flags);

}

我只是不确定您是否可以在Vertex类中包含Edge成员,因为这可能会创建循环引用。请先在没有这些成员的情况下进行测试。

编辑:

从此处阅读一些建议后:android parcelable referencing another parcelable circular dependence,我认为您可以尝试以下操作:

Edge类中,请勿在Vertex中写对writeToParcel()成员的引用。相反,请尝试以下操作:
public class Edge implements Parcelable {

    private Vertex from;
    private Vertex target;
    private double weigth;

    static HashMap<Long, Vertex> _parentsFrom = new HashMap<Long, Vertex>();
    static HashMap<Long, Vertex> _parentsTarget = new HashMap<Long, Vertex>();

    public long get_PKhash() { /* Return a unique identifier of your Edge object here */ }

    private ItemClass( Parcel in ) {
        (...)
        assertTrue( (from = _parentsFrom.remove( get_PKhash() )) != null );
        assertTrue( (target = _parentsTarget.remove( get_PKhash() )) != null );
    }

    public void writeToParcel( Parcel p, int args ) {
        (...)//Don't write to the parcel your from and target objects
        _parentsFrom.put( this.get_PKhash, from);
        _parentsTarget.put( this.get_PKhash, to);
    }
}   

请注意,您显然在Parcelable实现中没有循环引用。上面的解决方案是一个棘手的解决方法,只有在您可以确保在应用程序中唯一标识每个边缘实例时,它才有效。

希望能帮助到你。

关于java - 可包裹物体的循环引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20159632/

相关文章:

java - 在Java中声明类和接口(interface)的成员变量

javascript - 错误无法读取未定义的属性(读取 'configurations')。类型错误 : Cannot read properties of undefined (reading 'configurations' )

java - libgdx 中的线程化和移动 Sprite 的一般问题

android - 无法暂停 Activity - 在 android 中播放 bgm 时出现非法状态异常

android - 在末尾添加 View 并动态启动 View 寻呼机

java - 在二维ArrayList中查找某个值/元素

Java ArrayList<Integer> 到 ArrayList<String> 反之亦然

java - 如何从字符串中提取数字

Java8 Stream批处理以避免OutOfMemory

java - JSF2 和 PrettyFaces...如何获取原始 URL 或查询字符串?