我目前正在开发Android应用程序(我是开发Android应用程序的初学者),并且正在实现一个非常简单的类,该类能够处理位置(纬度,经度)和相应的地址(通过使用Geocoder API)。 我希望我的应用程序能够在两个活动之间传递我的类的一个实例,并且还可以返回结果,这样的结果也是该类的一个实例。
我已经写了我的类的声明来实现 Parcelable 类,就像这样(我的类名称是 OnePlace ):
public class OnePlace implements Parcelable {
private LatLng position;
private String address;
…
}
我已经使用能够实现 Parcelable 的方法实现了“ OnePlace”类,如Android开发者在线文档中所建议的那样: https://developer.android.com/reference/android/os/Parcelable
一切正常,我能够将班级的一个实例从一个活动转移到另一个活动,并因此将另一个实例取回。
这是片段代码,在其中我将类的实例添加为与意图一起发送的数据:
OnePlace item = new OnePlace(); // create an instance of the class with default values
Intent mapIntent = new Intent(adapterView.getContext(), MapsActivity.class);
mapIntent.putExtra("place", item); // add the item as extra data to the intent
startActivityForResult(mapIntent, 35);
在所调用的活动(此处为MapsActivity)中,我能够重建类实例的精确副本。
无论如何,这行得通,我对此感到满意。
现在,我想将类的实例存储在一个文件中,该文件将在下次启动我的应用程序时读取(一种永久存储的方式)。
为此,我在活动的 finish()方法内使用以下代码段(就在离开应用程序之前):
FileOutputStream outStream = openFileOutput("myFile.tmp", Context.MODE_PRIVATE);
ObjectOutputStream objectStream = new ObjectOutputStream(outStream);
objectStream.writeObject(item);
objectStream.close();
outStream.close();
如您所见,我将 ObjectOutputStream 类与 FileOutputStream 类一起使用,以便能够写入文件。 item 对象是我的 OnePlace 类的一个实例。我想将该实例永久存储到文件中,以备下次使用。
当我调用 writeObject(...)方法时,调用以“对象不可序列化”异常结束。在阅读了一些在线文档之后,明确指出我要“序列化”的类应实现 Serializable 接口(这是强制性的!)。
因此,我像这样更新了类的定义:
public class OnePlace implements Parcelable, Serializable {
private LatLng position;
private String address;
…
我稍微修改了类的定义,以实现 Parcelable 和 Serializable 接口。我不知道这是否是满足我的需求的最佳方法……
当我要调用 intent.putExtra(“ key”,item); 时,出现错误。实际上,Java编译器抱怨这样一个事实,即它不知道应实现哪个 putExtra 接口:具有Parcelable的接口还是具有Serializable接口的接口?它的反应似乎是合乎逻辑的,我认为如果我是一个人工编译器,我可能会问同样的问题。
那么,现在,我该如何解决该问题?有人有主意吗?也许,我要实现两个目标(将类实例转移到另一个活动并永久存储一个实例)的方法不是最好的方法吗?你有什么建议吗?
我非常感谢您的回答。
查尔斯
答案 0 :(得分:0)
最后,我设法找到了一个方便的优雅解决方案。如果其他寻求序列化对象的人可能对它感兴趣,我只是想发布我的操作方法。
在我的 OnePlace 类的声明中,我最终仅实现了 Parcelable 接口,以便能够在两个活动之间传递该类的实例(我没有再实现 Serialize 接口)。
public class OnePlace implements Parcelable {
private LatLng position;
private String address;
…
};
然后,我在类中添加了以下新方法:
public String toJSON() {
JSONObject jsonObj = new JSONObject();
try {
jsonObj.put("address", address);
jsonObj.put("latitude", position.latitude);
jsonObj.put("longitude", position.longitude);
return jsonObj.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
该方法会创建一个包含位置信息(地址,纬度和经度)的JSON对象,然后返回等效的字符串(将用于进一步导出位置信息)。
然后,在我的 MainActivity.finish()方法中,构建一个String的数组列表,每个字符串包含与OnePlace类实例相关联的JSON对象的String表示形式。 完成此操作后,我便可以序列化我的 ArrayList ,然后将其序列化(Java编译器不会抱怨!)。这给了我我在应用偏好设置中写的长字符串。
代码如下:
public void finish() {
ArrayList<String> listInstances = new ArrayList<String>();
for(OnePlace item: listOfPlaces) {
listInstances.add(item.toJSON());
}
try {
ObjectSerializer objSerializer = new ObjectSerializer();
String serializedStr = objSerializer.serialize(listInstances);
myPrefs.edit().putString("places", serializedStr).apply();
} catch (Exception e) {
e.printStackTrace();
}
}
现在,在我的 MainActivity.onCreate()方法中,我从应用程序首选项中读取字符串,并将其转换回OneClass实例,如下所示:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// This is an array list that will contain all OnePlace instances
listOfPlaces = new ArrayList<OnePlace>();
myPreferences = this.getSharedPreferences("…", MODE_PRIVATE);
// I read back the String containing the serialized ArrayList
String placesStr = myPreferences.getString("places");
// An array list that will contain the list of JSONObjects, one object representing one instance on the OnePlace class
ArrayList<String> jsonObjList;
// I create a new ObjectSerializer object
ObjectSerializer objSerializer = new ObjectSerializer();
// Then, I deserialize into a list of JSONObjects
try {
// The myList object contains a list of JSONObjects
jsonObjList = (ArrayList<String>)objSerializer.deserialize(placesStr);
// I loop through the list of JSONObjects
for(String str: jsonObjList) {
// I create a JSONObject with one single string
JSONObject myJson = new JSONObject(str);
// Then, I get the values back and I use them to create a OnePlace class instance
LatLng position = new LatLng(myJson.getDouble("latitude"), myJson.getDouble("longitude"));
OnePlace myPlace = new OnePlace(position, myJson.getString("address");
// And finally, I add that OnePlace instance into my list of places
listOfPlaces.add(myPlace);
}
} catch (Exception e) {
e.printStackTrace();
};
所以,我在这里总结一下我是如何进行操作的:
对于保存过程,我执行以下操作:
对于还原过程,我执行以下操作:
效果很好!
答案 1 :(得分:0)
我建议您在“活动”,“片段”之间传递数据时使用Gson序列化。这是非常容易和轻量级的库。您的应用示例;
Gson gson = new Gson();
OnePlace item = new OnePlace(); // create an instance of the class with default values
Intent mapIntent = new Intent(adapterView.getContext(), MapsActivity.class);
mapIntent.putExtra("place", gson.toJson(item)); // add the item as extra data to the intent
startActivityForResult(mapIntent, 35);
在MapsActivity.class中
Gson gson = new Gson();
String jsonPlace = getIntent().getStringExtra("place");
Place passedItem = gson.fromJson(jsonPlace, Place.class);