【问题标题】:Android ArrayList<Location> passing between activitiesAndroid ArrayList<Location> 在活动之间传递
【发布时间】:2012-08-29 11:52:02
【问题描述】:

我有一个简单的 Track 类,它存储有关路线的信息:

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;

import android.location.Location;

public class Track implements Serializable {
    private static final long serialVersionUID = -5317697499269650204L;

    private Date date;
    private String name;
    private int time;
    private double distance, speed;
    private ArrayList<Location> route;

    public Track(String name, int time, double distance, ArrayList<Location> route) {
        this.date = new Date();
        this.name = name;
        this.time = time;
        this.distance = distance;
        this.speed = distance / (time / 3600.);
        this.route = route;
    }

    public String getDate() {
        return String.format("Date: %1$td-%1$tb-%1$tY%nTime: %1$tH:%1$tM:%1$tS", date);
    }

    public String getName() {
        return name;
    }

    public int getTime() {
        return time;
    }

    public double getDistance() {
        return distance;
    }

    public float getSpeed() {
        return (float) speed;
    }

    public ArrayList<Location> getRoute() {
        return route;
    }

    @Override
    public String toString() {
        return String.format("Name: %s%nDate: %2$td-%2$tb-%2$tY%nTime: %2$tH:%2$tM:%2$tS", name, date);
    }
}

我将它从一个活动传递到另一个活动:

Intent showTrackIntent = new Intent(TabSavedActivity.this, ShowTrackActivity.class);
showTrackIntent.putExtra("track", adapter.getItem(position));
startActivity(showTrackIntent);

在哪里(Track 对象是 ListView 上的元素)。 传递 Track 对象时出错:

java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = classes.Track)

发生了什么?

【问题讨论】:

  • 你应该实现 Parcalabe 接口。
  • 这个错误是因为你的私有变量没有设置器,所以序列化过程没有办法设置这些变量。尝试编写设置器和测试并发布任何错误。
  • @eternalmatt 的评论毫无意义,因为您在 写入 对象(即:序列化它)时遇到错误,因此您不需要设置器。在任何情况下,Java 序列化都不需要 setter 或 getter 方法。
  • 序列化不需要设置器。

标签: android location serializable parcelable


【解决方案1】:

我认为问题在于Location 不可序列化。在尝试序列化 Location 对象时遇到问题的人提出了很多关于 SE 的问题。但是,LocationParcelable,所以也许你会更好地为你的班级实现Parcelable 而不是使用Serializable

【讨论】:

  • 我尝试实现 Parcelable 接口,但是我在 parceling ArrayList 时遇到了问题。我不知道我应该使用什么:readList (route, Location.class.getClassLoader()) 或 readTypedList(route, Location.CREATOR) - 它们都不起作用。
  • 您应该可以使用writeTypedList/readTypedListwriteList/readArrayListwriteList/readList 来执行此操作。你遇到了什么错误?
  • 所以我实现了 parcelable 并且一切正常,直到另一个活动尝试从 parcel 中读取,尤其是读取 ArrayList。错误是:java.lang.RuntimeException: Parcel android.os.Parcel@40609748: Unmarshalling unknown type code 6357098 at offset 160。我应该如何像你一样格式化 cmets?
  • 我看了你的回答并发表了评论。您将日期写到包裹上,但从未读回。这会导致坏事发生。要格式化您的 cmets,您可以使用反引号来获得“代码样式”,或者您可以使用双星号来获得粗体等。点击评论框右侧的蓝色“帮助”链接。
【解决方案2】:

目前的代码是:

包类;

import java.util.ArrayList;
import java.util.Date;

import android.location.Location;
import android.os.Parcel;
import android.os.Parcelable;

public class Track implements Parcelable {
    private String name, date;
    private int time;
    private double distance, speed;
    private ArrayList<Location> route;

public Track(String name, int time, double distance, Date date, ArrayList<Location> route) {
    this.name = name;
    this.date = formatDate(date);
    this.time = time;
    this.distance = distance;
    this.route = route;

    this.speed = distance / (time / 3600.);
}

public void writeToParcel(Parcel dest, int flags) {
    dest.writeStringArray(new String[] { name, date });
    dest.writeInt(time);
    dest.writeDouble(distance);
    dest.writeSerializable(date);
    dest.writeTypedList(route);
}

private Track(Parcel in) {
    String[] strings = new String[2];
    in.readStringArray(strings);

    this.name = strings[0];
    this.date = strings[1];
    this.time = in.readInt();
    this.distance = in.readDouble();

    route = new ArrayList<Location>();
    in.readTypedList(route, Location.CREATOR);

    this.speed = distance / (time / 3600.);
}

public static final Parcelable.Creator<Track> CREATOR = new Parcelable.Creator<Track>() {

    public Track createFromParcel(Parcel in) {
        return new Track(in);
    }

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

public String getName() {
    return name;
}

public String getDate() {
    return date;
}

public int getTime() {
    return time;
}

public double getDistance() {
    return distance;
}

public float getSpeed() {
    return (float) speed;
}

public ArrayList<Location> getRoute() {
    return route;
}

public String formatDate(Date date) {
    return String.format("Date: %1$td-%1$tb-%1$tY%nTime: %1$tH:%1$tM:%1$tS", date);
}

@Override
public String toString() {
    return String.format("Name: %s%nDate: %s", name, date);
}

public int describeContents() {
    return 0;
}

}

我不知道为什么,但是当我通过活动传递我的 Track 时,我在路由列表中只得到一个元素,即使我在新意图开始之前检查了它并且有完整列表。

【讨论】:

  • 您将日期写入包裹(使用dest.writeSerializable(date)),但在拆包时没有读取它(在构造函数Track(Parcel in) 中。这就是为什么它在尝试读取它时失败的原因。使用Parcelable 时,您绝对需要确保您阅读的内容与您所写的内容完全相同。
  • 代码呢:route = new ArrayList&lt;Location&gt;(); in.readTypedList(route, Location.CREATOR);
  • 如文档所述:“读入包含特定对象类型的给定列表项,这些对象类型是在当前 dataPosition() 处使用 writeTypedList(List) 写入的。”我不明白“在当前的dataPosition()”到底是什么意思。可能有问题。
  • 不不不。您仍在将“日期”字段写入dest.writeSerializable(date) 中的包裹,但是当您拆开包裹时,您并没有看到它。您开始读取 Location 数组。那是你的问题。请从writeToParcel() 中删除dest.writeSerializable(date)
  • A Parcel 不是哈希表。它不包含键/值对。它只是一个字节流。您必须确保以与编写它们时完全相同的顺序读取完全相同的数据类型。否则你会得到垃圾、崩溃或其他坏东西。
【解决方案3】:

我认为该解决方案现已准备就绪。代码如下:

import java.util.ArrayList;
import java.util.Date;

import android.location.Location; 
import android.os.Parcel;
import android.os.Parcelable;

public class Track implements Parcelable {
private String name, date;
private int time;
private double distance, speed;
private ArrayList<Location> route;

public Track(String name, int time, double distance, Date date, ArrayList<Location> route) {
    this.name = name;
    this.date = formatDate(date);
    this.time = time;
    this.distance = distance;
    this.route = route;

    this.speed = distance / (time / 3600.);
}

public void writeToParcel(Parcel dest, int flags) {
    dest.writeStringArray(new String[] { name, date });
    dest.writeInt(time);
    dest.writeDouble(distance);
    dest.writeTypedList(route);
}

private Track(Parcel in) {
    String[] strings = new String[2];
    in.readStringArray(strings);
    this.name = strings[0];
    this.date = strings[1];

    this.time = in.readInt();
    this.distance = in.readDouble();

    route = new ArrayList<Location>();
    in.readTypedList(route, Location.CREATOR);

    this.speed = distance / (time / 3600.);
}

public static final Parcelable.Creator<Track> CREATOR = new Parcelable.Creator<Track>() {

    public Track createFromParcel(Parcel in) {
        return new Track(in);
    }

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

public String getName() {
    return name;
}

public String getDate() {
    return date;
}

public int getTime() {
    return time;
}

public double getDistance() {
    return distance;
}

public float getSpeed() {
    return (float) speed;
}

public ArrayList<Location> getRoute() {
    return route;
}

public String formatDate(Date date) {
    return String.format("Date: %1$td-%1$tb-%1$tY%nTime: %1$tH:%1$tM:%1$tS", date);
}

@Override
public String toString() {
    return String.format("Name: %s%nDate: %s", name, date);
}

public int describeContents() {
    return 0;
}
}

David Wasser您非常有帮助,谢谢!

【讨论】:

  • 很高兴能提供帮助。我现在可以笑着回家了:-)
  • 嗯.. 但这里有另一个问题。为什么当我尝试将 ArrayList 序列化为文件时出现 NotSerializableException ..?
  • 你能用stacktrace发布logcat吗?
【解决方案4】:

序列化:

    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(savedTracksFile));
    oos.writeObject(serializedTracks);
    oos.close();

反序列化:

    ObjectInputStream ois = new ObjectInputStream(new FileInputStream(savedTracksFile));
    serializedTracks = (ArrayList<Track>) ois.readObject();
    ois.close();

savedTracksFile 在哪里:

    File savedLocationsDirectory = new File(Environment.getExternalStorageDirectory().getPath().concat("/AppFolder"));
    if (!savedLocationsDirectory.exists()) savedLocationsDirectory.mkdirs();
    savedTracksFile = new File(savedLocationsDirectory, "savedTracks.gc");

【讨论】:

  • 我无法序列化我的Track 类对象,因为Location 对象不可序列化。我将位置的ArrayList 更改为HashMap&lt;Double, Double&gt;,因为实际上我只需要纬度和经度,所以我认为这是保留它、在活动之间移动以及序列化到文件中的简单方法。
  • 但它以不同的方式混合点写入地图。也许我应该实现自己的类对,并将其保存到ArrayList
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-30
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 2012-11-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多