1

with kotlin, having a Data class implements Parcelable

seems there are two way of defining the CREATOR: Parcelable in the companion:

1.

data class Data (
    @SerializedName("id")
    val id: String?,
    @SerializedName("blob")
    val blob: String?
) : Parcelable {

... ...
companion object CREATOR : Parcelable.Creator<Data> {
    override fun createFromParcel(parcel: Parcel): Data {
        return Data(parcel)
    }

    override fun newArray(size: Int): Array<Data?> {
        return arrayOfNulls(size)
    }
}

}

2

data class Data (
    @SerializedName("id")
    val id: String?,
    @SerializedName("blob")
    val blob: String?
) : Parcelable {

... ...

companion object {

    @JvmField val CREATOR: Parcelable.Creator<Data> = object : Parcelable.Creator<Data> {
        override fun createFromParcel(parcel: Parcel): Data {
            return Data(parcel)
        }

        override fun newArray(size: Int): Array<Data?> {
            return arrayOfNulls(size)
        }
    }

}

}

the corresponding java decompiled code is

1

   @JvmField
   @NotNull
   public static final Creator CREATOR = (Creator)(new Creator() {
   @NotNull
   public Data createFromParcel(@NotNull Parcel parcel) {
     Intrinsics.checkParameterIsNotNull(parcel, "parcel");
     return new Data(parcel, (DefaultConstructorMarker)null);
  }

  // $FF: synthetic method
  // $FF: bridge method
  public Object createFromParcel(Parcel var1) {
     return this.createFromParcel(var1);
  }

  @NotNull
  public Data[] newArray(int size) {
     return new Data[size];
  }

  // $FF: synthetic method
  // $FF: bridge method
  public Object[] newArray(int var1) {
     return this.newArray(var1);
  }
});

2

  public static final Data.CREATOR CREATOR = new Data.CREATOR((DefaultConstructorMarker)null);

  public static final class CREATOR implements Creator {
  @NotNull
  public Data createFromParcel(@NotNull Parcel parcel) {
     Intrinsics.checkParameterIsNotNull(parcel, "parcel");
     return new Data(parcel);
  }

  // $FF: synthetic method
  // $FF: bridge method
  public Object createFromParcel(Parcel var1) {
     return this.createFromParcel(var1);
  }

  @NotNull
  public Data[] newArray(int size) {
     return new Data[size];
  }

  // $FF: synthetic method
  // $FF: bridge method
  public Object[] newArray(int var1) {
     return this.newArray(var1);
  }

  private CREATOR() {
  }

  // $FF: synthetic method
  public CREATOR(DefaultConstructorMarker $constructor_marker) {
     this();
  }
}

and with kotlin to get a List<Data> from parcel could be done:

parcel.createTypedArrayList(Data.CREATOR)

and in java it could be:

List list = (List)(new ArrayList());
parcel.readTypedList(list, (Creator)Data.CREATOR);

Seems in kotlin both CREATOR in the companion are fine.

What is the difference, and which is better to use?

lannyf
  • 9,865
  • 12
  • 70
  • 152
  • 1
    Why don't you use the `@Parcelize` annotation to generate all of this automatically? https://kotlinlang.org/docs/tutorials/android-plugin.html#parcelable – yole Sep 28 '18 at 16:15
  • thanks @yole! mainly because of the "experimental ", but definitely will experiment with it. Now just trying to figure out what is the right way. – lannyf Sep 28 '18 at 16:26
  • 1
    I would prefer `companion object { @JvmField val CREATOR ..}` because that's documented to create a static field named `CREATOR` while a named companion feels more like accidentally doing the right thing. Also less chance of confusing people because it's more in line with typical examples that have "anonymous" companion objects – zapl Sep 28 '18 at 19:28
  • @zapl, if you could put is as the answer I will put approve on it, thanks! – lannyf Oct 08 '18 at 13:47
  • I have a similar question, because for the first way, Lint is complaining that CREATOR is not annotated with `@JvmField`. In my case, I'm using an interface, not a data class. If I switch to the second way, then the implementing classes need to individually declare their own CREATOR properties. – Mark Dec 08 '20 at 14:02

0 Answers0