Parcelable 在没有正确实施的情况下工作
Parcelable works without correct implementation
在 Android 应用程序中,我将一个包从 Activity 发送到一个片段。
public class Bar implements Parcelable {
private Map<String, String> hash;
private int id;
protected Bar(Parcel in) {
id = in.readInt();
}
public Bar(int id, Map<String,String> map){
this.hash=map;
this.id=id;
}
public static final Creator<Bar> CREATOR = new Creator<Bar>() {
@Override
public Bar createFromParcel(Parcel in) {
return new Bar(in);
}
@Override
public Bar[] newArray(int size) {
return new Bar[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(id);
}
}
我使用了 Android Studios Implement Parcelable inteli sense 帮助并自动生成了上述代码,但它没有实现地图。
当我像这样将它发送到我的片段时:
Map<String,String> map = new HashMap<String, String>();
map.put("foo","bar");
map.put("foobar","barfoo");
Bar foo = new Bar(1,map);
MyFragment fragment = new MyFragment();
Bundle bundle = new Bundle();
fragment.setArguments(bundle);
bundle.putParcelable("foo",foo);
FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.container, fragment, "foo");
fragmentTransaction.commit();
当 Map 出现在片段中时,它似乎以某种方式包含内容。为什么是这样?我期望的行为是 Id 被转移并且 Map 被跳过。
这可以通过创建一个 Activity、一个片段和我的 Bar 并将其作为一个 Bundle 发送来重复。
我尝试寻找答案,但不太确定如何提出问题。
这是错误还是应该以这种方式工作的功能?
Bundle不仅有Parcelable对象存储实现,还有Serializable。如果你看一下 HashMap 的 class 你会看到它实现了 Serializable 接口:
public class HashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
打包是延迟完成的,这意味着当您将 Bar
实例传递给 Fragment
时,它不会被打包。 IE。 writeToParcel
未调用。
Parceling 非常昂贵(就资源而言),因此最好尽可能避免。如果 Bundle
没有发送到另一个进程,则不需要打包它。通常在涉及 IPC 时进行打包。因此,即使在配置更改期间,也无需打包 Bundle
。但是,如果当 activity 在后台时您的进程被终止,则参数 Bundle
将被打包,因为它存储在另一个进程中。
在 Intent
.
中发送时也是如此
因此,在您的情况下,Map
会在实际打包实例时丢失。它仍然存在是因为它并没有真正被打包并且 Fragment 接收到 Bar
.
的完全相同的实例
在 Android 应用程序中,我将一个包从 Activity 发送到一个片段。
public class Bar implements Parcelable {
private Map<String, String> hash;
private int id;
protected Bar(Parcel in) {
id = in.readInt();
}
public Bar(int id, Map<String,String> map){
this.hash=map;
this.id=id;
}
public static final Creator<Bar> CREATOR = new Creator<Bar>() {
@Override
public Bar createFromParcel(Parcel in) {
return new Bar(in);
}
@Override
public Bar[] newArray(int size) {
return new Bar[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(id);
}
}
我使用了 Android Studios Implement Parcelable inteli sense 帮助并自动生成了上述代码,但它没有实现地图。
当我像这样将它发送到我的片段时:
Map<String,String> map = new HashMap<String, String>();
map.put("foo","bar");
map.put("foobar","barfoo");
Bar foo = new Bar(1,map);
MyFragment fragment = new MyFragment();
Bundle bundle = new Bundle();
fragment.setArguments(bundle);
bundle.putParcelable("foo",foo);
FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.container, fragment, "foo");
fragmentTransaction.commit();
当 Map 出现在片段中时,它似乎以某种方式包含内容。为什么是这样?我期望的行为是 Id 被转移并且 Map 被跳过。 这可以通过创建一个 Activity、一个片段和我的 Bar 并将其作为一个 Bundle 发送来重复。 我尝试寻找答案,但不太确定如何提出问题。
这是错误还是应该以这种方式工作的功能?
Bundle不仅有Parcelable对象存储实现,还有Serializable。如果你看一下 HashMap 的 class 你会看到它实现了 Serializable 接口:
public class HashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
打包是延迟完成的,这意味着当您将 Bar
实例传递给 Fragment
时,它不会被打包。 IE。 writeToParcel
未调用。
Parceling 非常昂贵(就资源而言),因此最好尽可能避免。如果 Bundle
没有发送到另一个进程,则不需要打包它。通常在涉及 IPC 时进行打包。因此,即使在配置更改期间,也无需打包 Bundle
。但是,如果当 activity 在后台时您的进程被终止,则参数 Bundle
将被打包,因为它存储在另一个进程中。
在 Intent
.
因此,在您的情况下,Map
会在实际打包实例时丢失。它仍然存在是因为它并没有真正被打包并且 Fragment 接收到 Bar
.