如何使我的自定义对象 Parcelable?
Posted
技术标签:
【中文标题】如何使我的自定义对象 Parcelable?【英文标题】:How can I make my custom objects Parcelable? 【发布时间】:2011-11-03 03:16:30 【问题描述】:我正在尝试使我的对象可包裹。但是,我有自定义对象,这些对象具有我制作的其他自定义对象的 ArrayList
属性。
最好的方法是什么?
【问题讨论】:
【参考方案1】:您可以找到here、here (code is taken here) 和 here 的一些示例。
您可以为此创建一个 POJO 类,但您需要添加一些额外的代码来使其成为Parcelable
。看看实现。
public class Student implements Parcelable
private String id;
private String name;
private String grade;
// Constructor
public Student(String id, String name, String grade)
this.id = id;
this.name = name;
this.grade = grade;
// Getter and setter methods
.........
.........
// Parcelling part
public Student(Parcel in)
String[] data = new String[3];
in.readStringArray(data);
// the order needs to be the same as in writeToParcel() method
this.id = data[0];
this.name = data[1];
this.grade = data[2];
@Оverride
public int describeContents()
return 0;
@Override
public void writeToParcel(Parcel dest, int flags)
dest.writeStringArray(new String[] this.id,
this.name,
this.grade);
public static final Parcelable.Creator CREATOR = new Parcelable.Creator()
public Student createFromParcel(Parcel in)
return new Student(in);
public Student[] newArray(int size)
return new Student[size];
;
一旦你创建了这个类,你就可以像这样通过Intent
轻松地传递这个类的对象,并在目标活动中恢复这个对象。
intent.putExtra("student", new Student("1","Mike","6"));
在这里,学生是您从捆绑包中解包数据所需的密钥。
Bundle data = getIntent().getExtras();
Student student = (Student) data.getParcelable("student");
此示例仅显示 String
类型。但是,您可以打包任何类型的数据。试试看。
编辑:另一个example,由Rukmal Dias 建议。
【讨论】:
@Rukmal Dias 10x。事实上,我必须编辑我的答案并添加一些代码,因为这些链接在未来的某一天将不再有效。 OP 询问如何传递自定义对象而不是常规字符串。任何人都可以传递常规字符串。你能解释一下如何用 CUSTOM OBJECT 创建它 如果我只使用 LocalBroadcastManager 发送编码/解码部分,我是否必须实际实现它们?实现 Parcelable 和 put as extra 就够了吗? 为什么要使用字符串数组而不是逐个写入字符串? 在writeToParcel
方法中创建字符串数组时成员的顺序是否重要?【参考方案2】:
这是一个从您创建的类创建 Parcelable 类的网站:
http://www.parcelabler.com/
【讨论】:
【参考方案3】:IntelliJ IDEA 和 android Studio 有插件:
★Android Parcelable code generator(阿帕奇License2.0) Auto Parcel(麻省理工学院License) SerializableParcelable Generator(麻省理工学院License) Parcelable Code Generator (for Kotlin) (Apache License 2.0)这些插件根据类中的字段生成 Android Parcelable 样板代码。
【讨论】:
用一种新的方式来做这些事情,太棒了!【参考方案4】:1。导入Android Parcelable code generator
2。创建一个类
public class Sample
int id;
String name;
3。 Generate > Parcelable from menu
完成。
【讨论】:
对于那些不知道浏览存储库对话框在哪里的人:File > Settings... > Plugins
并点击Browse repositories...
按钮。
谢谢,帮了大忙!【参考方案5】:
怎么样?带注释。
您只需使用特殊注释对 POJO 进行注释,其余的由库完成。
警告!
我不确定 Hrisey、Lombok 和其他代码生成库是否与 Android 的新构建系统兼容。他们可能会也可能不会很好地使用热交换代码(即 jRebel、Instant Run)。
优点:
代码生成库将您从样板源代码中解救出来。 注释让你的课堂更漂亮。缺点:
它适用于简单的类。使复杂的类可打包可能很棘手。 Lombok 和 AspectJ 不能很好地配合使用。 [details] 查看我的警告。赫里斯
警告!
Hrisey 在 Java 8 中存在一个已知问题,因此目前无法用于 Android 开发。 见#1 Cannot find symbol errors (JDK 8)。
Hrisey 基于Lombok。使用Hrisey的Parcelable类:
@hrisey.Parcelable
public final class POJOClass implements android.os.Parcelable
/* Fields, accessors, default constructor */
现在你不需要实现 Parcelable 接口的任何方法。 Hrisey 将在预处理阶段生成所有需要的代码。
Gradle 依赖项中的 Hrisey:
provided "pl.mg6.hrisey:hrisey:$hrisey.version"
See here 用于支持的类型。 ArrayList
就是其中之一。
为您的 IDE 安装一个插件 - Hrisey xor Lombok* - 并开始使用其惊人的功能!
* 不要同时启用 Hrisey 和 Lombok 插件,否则在 IDE 启动期间会出现错误。
打包机
使用Parceler的Parcelable类:
@java.org.parceler.Parcel
public class POJOClass
/* Fields, accessors, default constructor */
要使用生成的代码,您可以直接引用生成的类,或通过Parcels
实用程序类使用
public static <T> Parcelable wrap(T input);
要取消引用@Parcel
,只需调用Parcels
类的以下方法
public static <T> T unwrap(Parcelable input);
Gradle 依赖项中的 Parceler:
compile "org.parceler:parceler-api:$parceler.version"
provided "org.parceler:parceler:$parceler.version"
查看README 以获得支持的attribute types。
自动包裹
AutoParcel 是一个AutoValue 扩展,可以生成 Parcelable 值。
只需将 implements Parcelable
添加到您的 @AutoValue
注释模型中:
@AutoValue
abstract class POJOClass implements Parcelable
/* Note that the class is abstract */
/* Abstract fields, abstract accessors */
static POJOClass create(/*abstract fields*/)
return new AutoValue_POJOClass(/*abstract fields*/);
Gradle 构建文件中的 AutoParcel:
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
repositories
/*...*/
maven url "https://clojars.org/repo/"
dependencies
apt "frankiesardo:auto-parcel:$autoparcel.version"
纸包
PaperParcel 是一个注解处理器,可以自动为 Kotlin 和 Java 生成类型安全的 Parcelable 样板代码。 PaperParcel 通过 AutoValue 扩展支持 Kotlin 数据类、Google 的 AutoValue,或者只是普通的 Java bean 对象。
来自docs的用法示例。
使用@PaperParcel
注释您的数据类,实现PaperParcelable
,并添加PaperParcelable.Creator
的JVM 静态实例,例如:
@PaperParcel
public final class Example extends PaperParcelable
public static final PaperParcelable.Creator<Example> CREATOR = new PaperParcelable.Creator<>(Example.class);
private final int test;
public Example(int test)
this.test = test;
public int getTest()
return test;
对于 Kotlin 用户,请参阅 Kotlin Usage;对于 AutoValue 用户,请参阅AutoValue Usage。
ParcelableGenerator
ParcelableGenerator (README 是用中文写的,我看不懂。欢迎讲中文的开发者对此答案的贡献)
来自README 的用法示例。
import com.baoyz.pg.Parcelable;
@Parcelable
public class User
private String name;
private int age;
public String getName()
return name;
public void setName(String name)
this.name = name;
public int getAge()
return age;
public void setAge(int age)
this.age = age;
android-apt 插件有助于将注释处理器与 Android Studio 结合使用。
【讨论】:
【参考方案6】:在 Android Studio 中创建不带插件的 Parcelable 类
在你的类中实现 Parcelable,然后将光标放在“implements Parcelable”上并点击Alt+Enter
并选择Add Parcelable implementation
(见图)。就是这样。
【讨论】:
【参考方案7】:我找到了创建 Parcelable 类
的最简单方法【讨论】:
它适用于小数据,但如果我们采用复杂数据,这将不起作用【参考方案8】:很简单,你可以使用android studio上的一个插件来制作对象Parcelables。
public class Persona implements Parcelable
String nombre;
int edad;
Date fechaNacimiento;
public Persona(String nombre, int edad, Date fechaNacimiento)
this.nombre = nombre;
this.edad = edad;
this.fechaNacimiento = fechaNacimiento;
@Override
public int describeContents()
return 0;
@Override
public void writeToParcel(Parcel dest, int flags)
dest.writeString(this.nombre);
dest.writeInt(this.edad);
dest.writeLong(fechaNacimiento != null ? fechaNacimiento.getTime() : -1);
protected Persona(Parcel in)
this.nombre = in.readString();
this.edad = in.readInt();
long tmpFechaNacimiento = in.readLong();
this.fechaNacimiento = tmpFechaNacimiento == -1 ? null : new Date(tmpFechaNacimiento);
public static final Parcelable.Creator<Persona> CREATOR = new Parcelable.Creator<Persona>()
public Persona createFromParcel(Parcel source)
return new Persona(source);
public Persona[] newArray(int size)
return new Persona[size];
;
【讨论】:
你是什么插件?【参考方案9】:现在您可以使用 Parceler 库将您的任何自定义类转换为 parcelable。只需使用 @Parcel 注释您的 POJO 类。 例如
@Parcel
public class Example
String name;
int id;
public Example()
public Example(int id, String name)
this.id = id;
this.name = name;
public String getName() return name;
public int getId() return id;
您可以创建 Example 类的对象并通过 Parcels 包装并通过 Intent 作为捆绑发送。例如
Bundle bundle = new Bundle();
bundle.putParcelable("example", Parcels.wrap(example));
现在要获取自定义类对象,只需使用
Example example = Parcels.unwrap(getIntent().getParcelableExtra("example"));
【讨论】:
【参考方案10】:Android parcable 有一些独特的东西。这些在下面给出:
-
您必须按照在包裹上放置数据的相同顺序读取包裹。
从包裹读取后包裹将清空。也就是说,如果您的包裹上有 3 个数据。然后在读取 3 次后包裹将是空的。
示例: 要创建一个 Parceble 类,它必须实现 Parceble。 Percable 有两种方法:
int describeContents();
void writeToParcel(Parcel var1, int var2);
假设你有一个 Person 类,它有 3 个字段,firstName、lastName 和 age。实现 Parceble 接口后。该界面如下:
import android.os.Parcel;
import android.os.Parcelable;
public class Person implements Parcelable
private String firstName;
private String lastName;
private int age;
public void setFirstName(String firstName)
this.firstName = firstName;
public String getFirstName()
return firstName;
public void setLastName(String lastName)
this.lastName = lastName;
public String getLastName()
return lastName;
public void setAge(int age)
this.age = age;
public int getAge()
return age;
@Override
public int describeContents()
return 0;
@Override
public void writeToParcel(Parcel parcel, int i)
parcel.writeString(firstName);
parcel.writeString(lastName);
parcel.writeInt(age);
在writeToParcel
方法中,我们正在按顺序在 Parcel 上写入/添加数据。在此之后,我们必须添加以下代码以从包裹中读取数据:
protected Person(Parcel in)
firstName = in.readString();
lastName = in.readString();
age = in.readInt();
public static final Creator<Person> CREATOR = new Creator<Person>()
@Override
public Person createFromParcel(Parcel in)
return new Person(in);
@Override
public Person[] newArray(int size)
return new Person[size];
;
这里,Person 类在写入过程中以相同的顺序接收包裹并获取数据。
现在在意图getExtra
和putExtra
代码如下:
放入额外的:
Person person=new Person();
person.setFirstName("First");
person.setLastName("Name");
person.setAge(30);
Intent intent = new Intent(getApplicationContext(), SECOND_ACTIVITY.class);
intent.putExtra()
startActivity(intent);
获得额外奖励:
Person person=getIntent().getParcelableExtra("person");
下面给出了完整的 Person 类:
import android.os.Parcel;
import android.os.Parcelable;
public class Person implements Parcelable
private String firstName;
private String lastName;
private int age;
public void setFirstName(String firstName)
this.firstName = firstName;
public String getFirstName()
return firstName;
public void setLastName(String lastName)
this.lastName = lastName;
public String getLastName()
return lastName;
public void setAge(int age)
this.age = age;
public int getAge()
return age;
@Override
public int describeContents()
return 0;
@Override
public void writeToParcel(Parcel parcel, int i)
parcel.writeString(firstName);
parcel.writeString(lastName);
parcel.writeInt(age);
protected Person(Parcel in)
firstName = in.readString();
lastName = in.readString();
age = in.readInt();
public static final Creator<Person> CREATOR = new Creator<Person>()
@Override
public Person createFromParcel(Parcel in)
return new Person(in);
@Override
public Person[] newArray(int size)
return new Person[size];
;
Hope this will help you
Thanks :)
【讨论】:
【参考方案11】:说:
bundle.putSerializable("key",(Serializable) object);
要获得:
List<Object> obj = (List<Object>)((Serializable)bundle.getSerializable("key"));
【讨论】:
如果对象没有实现Serializable
,这将导致ClassCastException
。
虽然这段代码 sn-p 可以解决问题,including an explanation 确实有助于提高您的帖子质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。也请尽量不要用解释性的 cmets 挤满你的代码,这会降低代码和解释的可读性!以上是关于如何使我的自定义对象 Parcelable?的主要内容,如果未能解决你的问题,请参考以下文章
在 XAML 中调用时,如何使我的自定义依赖项属性排序到顶部?
如何使我的自定义 HTML 小部件针对不同的屏幕尺寸显示不同?
如何使我的自定义 ViewModifier 仅适用于 SwiftUI 中符合(可识别和视图)的内容/视图?
Android Parcelable 和 Serializable