迁移到新的 kotlin-parcelize

Migrate to the new kotlin-parcelize

提问人:stefan.at.kotlin 提问时间:11/25/2020 最后编辑:stefan.at.kotlin 更新时间:10/13/2022 访问量:14238

问:

任何人都可以解释一下如何迁移到新的kotlin-parcelize

我试过了:

  1. 替换为 in app build.gradleapply plugin: 'kotlin-android-extensions'apply plugin: 'kotlin-parcelize'
  2. 替换为import kotlinx.android.parcel.Parcelizeimport kotlinx.parcelize.Parcelize

后者导致

Class 'ParcelZonedDateTime' is not abstract and does not implement abstract member public abstract fun describeContents(): Int defined in android.os.Parcelable

例如,在以下代码上:

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()
    }
}

那么,如何迁移到新的?kotlin-parcelize

更新:

基于评论:是的,我在 Kotlin 1.4.20(比 1.4.20-M2 更新)。Kyzer 是对的,IDE 中的错误(不是抽象的,也没有实现抽象成员公共抽象趣味 describeContents())可以而且必须被忽略。然而,我在使用泛型时遇到了一个问题:

import android.os.Parcelable
import kotlinx.parcelize.Parcelize

sealed class MyDialogEvent {
    @Parcelize
    data class Confirmed<T: Parcelable>(val identity: String, val data: T) : Parcelable
}

为此生成的代码是

@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;
    }
}

在编译过程中,我收到此错误(行号与示例代码不匹配,但您可以通过比较方法名称轻松识别匹配的行):

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()
Android Kotlin 可包裹

评论

1赞 Xid 11/25/2020
抱歉没有这方面的信息,但我肯定泛型不适用于注解,无论包或密封类如何,因为生成的类中静态上下文中的方法不知道泛型类型 T 是什么
3赞 dzeikei 11/30/2020
看起来 Parcelize 泛型错误是由 Kotlin 1.4.20 本身引入的,而不是插件迁移。如果您回滚并保留 Kotlin 1.4.20,我仍然会遇到同样的错误。kotlin-android-extensions
2赞 Saunik Singh 12/8/2020
我在 kotlin 1.4.21 中遇到了同样的问题,所以我将代码回滚到 1.4.10 中,它工作正常
1赞 okarakose 12/13/2020
我的项目中也有同样的问题。我尝试了 1.4.21 版本,但错误仍然存在。有人找到解决方案吗?这真的很烦人。
1赞 stefan.at.kotlin 12/14/2020
我没有进一步深入研究,但现在添加了赏金。希望有人对此有答案。或者也许这是一个错误和需要修复?):

答:

-4赞 Yijun Liu 12/3/2020 #1

更改此行: 导入 kotlinx.parcelize.Parcelize 自: 导入 kotlinx.android.parcel.Parcelize

评论

3赞 Barry Irvine 12/4/2020
但这已被弃用!这就是迁移的重点
-1赞 AndrazP 12/14/2020 #2

原始问题的答案:

如果您在 Android Studio 中看到以下错误:

Class 'ClassName' is not abstract and does not implement abstract member public abstract fun describeContents(): Int defined in android.os.Parcelable

确保您已将 Kotlin 依赖项和 Android Studio Kotlin 插件更新到 1.4.20 或更高版本。enter image description here更新插件后,请确保 File -> Invalidate Caches / Restart。这对我有用。

评论

4赞 Myroslav 2/12/2021
不幸的是,它对我不起作用。我的目标是 1.4.30 - 项目和 AS 插件,AS 版本 4.1.2。使缓存失效后,仍然存在同样的问题。
1赞 Ric17101 12/15/2020 #3

经过进一步检查,我认为带有 Parcel 构造的泛型类型无法编译,因为无法根据此引用确定通用类型。ParcelableT class

enter image description here

也许枚举可能是最后的手段。

22赞 esentsov 12/16/2020 #4

这是 kapt 中的一个错误,在这里报告。实际上,您发布的 java 代码是一个存根类,由 kapt 生成,用于在其上运行注解处理器(如您所见,没有真正的实现,只有结构和注解)。因此,作为一种解决方法,您可以将带有注释的代码移动到未启用 kapt 的单独模块中。 它本身不使用注解处理器来生成代码,它使用编译器插件直接发出 IR,我相信。@Parcelizekotlin-parcelize

更新:该问题已在 kotlin 1.5 中修复

评论

0赞 3366784 2/4/2021
我们将如何将代码移动到一个单独的模块中?这是否意味着第二个模块将有一个单独的 Gradle 文件?
0赞 David José Martínez Morales 12/16/2020 #5

我使用 Kotlin 版本 1.4.10:

implementation "org.jetbrains.kotlin:kotlin-stdlib:1.4.10"

但在我的模块中,只适用

id 'kotlin-android'
id 'kotlin-android-extensions'

它对我有用。

我所有的插件都适用于我的模块:

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'
}

评论

0赞 CoolMind 10/13/2021
然后你使用一个实现。另请参见 stackoverflow.com/questions/64981310/...kotlinx.android.parcel.Parcelize
0赞 RealityExpander 10/15/2022
查看本文,了解如何将@TypeParceler用于非基元类。medium.com/@chrisathanas/......
4赞 Leo N 11/4/2021 #6

这是为我工作,请仔细检查行的顺序

plugins {
    id 'kotlin-android'
    id 'kotlin-parcelize'
    id 'kotlin-kapt'    
   }

评论

0赞 RealityExpander 10/16/2022
我在这里写了一篇关于如何使用自定义@TypeParcelers的文章:medium.com/@chrisathanas/......