问题
Can anyone please explain how to migrate to the new kotlin-parcelize
?
I tried:
- Replace
apply plugin: 'kotlin-android-extensions'
withapply plugin: 'kotlin-parcelize'
in app build.gradle - Replace
import kotlinx.android.parcel.Parcelize
withimport kotlinx.parcelize.Parcelize
The latter one leads to
Class 'ParcelZonedDateTime' is not abstract and does not implement abstract member public abstract fun describeContents(): Int defined in android.os.Parcelable
on e.g. this code:
import androidx.annotation.Keep
import kotlinx.parcelize.Parcelize
import org.threeten.bp.ZonedDateTime
@Keep
@Parcelize
data class ParcelZonedDateTime(var value: ZonedDateTime?) :Parcelable {
override fun toString(): String {
return value.toString()
}
}
So, how to migrate to the new kotlin-parcelize
?
Update:
Based on comments: Yes, I am on Kotlin 1.4.20 (which is newer than 1.4.20-M2).Kyzer is right that the error in the IDE (is not abstract and does not implement abstract member public abstract fun describeContents()) can and has to be ignored. Yet I have an issue where I use Generics:
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
sealed class MyDialogEvent {
@Parcelize
data class Confirmed<T: Parcelable>(val identity: String, val data: T) : Parcelable
}
The generated code for this is
@kotlin.Metadata(mv = {1, 4, 1}, bv = {1, 0, 3}, k = 3)
public static final class Creator implements android.os.Parcelable.Creator<com.example.stackoverflow.MyDialogEvent.Confirmed> {
public Creator() {
super();
}
@org.jetbrains.annotations.NotNull()
@java.lang.Override()
public final com.example.stackoverflow.MyDialogEvent.Confirmed<T>[] newArray(int size) {
return null;
}
@org.jetbrains.annotations.NotNull()
@java.lang.Override()
public final com.example.stackoverflow.MyDialogEvent.Confirmed<T> createFromParcel(@org.jetbrains.annotations.NotNull()
android.os.Parcel in) {
return null;
}
}
and during compilation I get this error for it (line numbers won't match the sample code, but you can easily identify the matching lines by comparing the method names):
MyDialogEvent.java:167: error: non-static type variable T cannot be referenced from a static context
public final com.example.stackoverflow.MyDialogEvent.Confirmed<T>[] newArray(int size) {
MyDialogEvent.java:173: error: non-static type variable T cannot be referenced from a static context
public final com.example.stackoverflow.MyDialogEvent.Confirmed<T> createFromParcel(@org.jetbrains.annotations.NotNull()
回答1:
That's a bug in kapt and it's reported here. Actually the java code you posted is a stub class which generated by kapt to run annotation processors on it (as you can see, there is no real implementation, just the structure and annotations). So as a workaround you can move the code with @Parcelize
annotations to a separate module where you don't have kapt enabled. kotlin-parcelize
itself does not use annotation processors to generate code, it uses a compiler plugin to emit the IR directly I believe.
回答2:
Answer for original question:
If you see this error in Android Studio:
Class 'ClassName' is not abstract and does not implement abstract member public abstract fun describeContents(): Int defined in android.os.Parcelable
Make sure that you have updated both Kotlin dependency and Android Studio Kotlin plugin to 1.4.20 or later. After updating the plugin make sure to File -> Invalidate Caches / Restart. That worked for me.
回答3:
After further checking, I think Parcelable
generic type with Parcel constructing fails to compile because T class
can not be determined generically based from this reference.
Perhaps an enum could be the last resort.
回答4:
I use the Kotlin version 1.4.10:
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.4.10"
but in my module, only apply
id 'kotlin-android'
id 'kotlin-android-extensions'
and it work for me.
There is all my plugins apply in my module:
plugins {
id 'com.android.library'
id 'kotlin-android'
id 'kotlin-android-extensions'
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
id 'androidx.navigation.safeargs.kotlin'
}
回答5:
change this line: import kotlinx.parcelize.Parcelize to: import kotlinx.android.parcel.Parcelize
来源:https://stackoverflow.com/questions/64991110/migrate-to-the-new-kotlin-parcelize