Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Migrate to the new kotlin-parcelize

Can anyone please explain how to migrate to the new kotlin-parcelize?

I tried:

  1. Replace apply plugin: 'kotlin-android-extensions' with apply plugin: 'kotlin-parcelize' in app build.gradle
  2. Replace import kotlinx.android.parcel.Parcelize with import 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()
like image 765
stefan.at.wpf Avatar asked Nov 24 '20 16:11

stefan.at.wpf


People also ask

Is Viewbinding deprecated?

Kotlin Android Extensions is deprecated, which means that using Kotlin synthetics for view binding is no longer supported.

How do I use kotlin-Parcelize?

Just add the @Parcelize annotation to a class implementing the Parcelable interface and the Parcelable implementation will be generated automatically. This is the same example as in the previous article, in just 2 lines of code. The class can be a data class but it's optional.

How do I Parcelize my kotlin data class?

There are 3 ways you can make your class Parcelable: Implementing the Parcelable interface and defining the serialization yourself (The traditional way) Using Android Studio plugins, like Android Parcelable code generator. Using annotation-based libraries, like Parceler.

How to migrate from Kotlin-Android-extensions Kotlin plugin to viewbinding and Kotlin parcelize?

If you want to give it a try you need to install the Kotlin EAP Plugin for IntelliJ IDEA or Android Studio Select Tools → Kotlin → Configure Kotlin Plugin Updates. Click Check again. Here is what you should do to migrate from kotlin-android-extensions Kotlin plugin to ViewBinding and kotlin-parcelize plugin

What happened to the parcelize annotation in Kotlin?

Don’t forget that Parcelize feature in Kotlin is part of the kotlin-android-extensions compiler plugin, so removing the plugin will endup making all your Parcelable classes not compiling if they depend on the Parcelize annotation. JetBrains extracted the Parcelize from Kotlin Android Extensions to a new plugin, kotlin-parcelize

What is parcelable in Android with Kotlin?

On Android, Parcelable is an interface that a class can implement to be passed within an Intent from an Activity to another one, this way, transporting data from one Activity to another one. But with thanks to KOTLIN, we do not need to override these methods. We can directly use parcelize to handle this with minimal code.

How to add Kotlin-parcelize plugin to your project?

Add binding object in your activities and fragments and use it to set the content view and access views from your xml files. If you are using Parcelize annotation, then add the new kotlin-parcelize plugin into your modules build.gradle files and change the import statements as mentioned above.


Video Answer


3 Answers

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.

Update: the issue is fixed in kotlin 1.5

like image 97
esentsov Avatar answered Oct 07 '22 00:10

esentsov


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.

enter image description here

Perhaps an enum could be the last resort.

like image 33
Ric17101 Avatar answered Oct 07 '22 01:10

Ric17101


This is work for me, please check the order of lines carefully

plugins {
    id 'kotlin-android'
    id 'kotlin-parcelize'
    id 'kotlin-kapt'    
   }
like image 3
Leo NGUYEN Avatar answered Oct 07 '22 00:10

Leo NGUYEN