【问题标题】:Migrate to the new kotlin-parcelize迁移到新的 kotlin-parcelize
【发布时间】:2020-11-24 16:50:41
【问题描述】:

谁能解释一下如何迁移到newkotlin-parcelize

我试过了:

  1. 在 app build.gradle 中将 apply plugin: 'kotlin-android-extensions' 替换为 apply plugin: 'kotlin-parcelize'
  2. import kotlinx.android.parcel.Parcelize 替换为import 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

更新:

基于 cmets:是的,我使用的是 Kotlin 1.4.20(比 1.4.20-M2 更新)。Kyzer 认为 IDE 中的错误是正确的(不是抽象的,也没有实现抽象成员public abstract fun 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()

【问题讨论】:

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

标签: android kotlin parcelable


【解决方案1】:

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

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

【讨论】:

  • 我们将如何将代码移动到单独的模块中?这是否意味着第二个模块会有一个单独的 Gradle 文件?
【解决方案2】:

经过进一步检查,我认为 Parcelable 具有 Parcel 构造的泛型类型无法编译,因为无法根据此 reference 泛型确定 T class

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • 精彩绝伦!很有帮助!
    【解决方案4】:

    我使用的是 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'
    }
    

    【讨论】:

    【解决方案5】:

    原始问题的答案:

    如果您在 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 或更高版本。 更新插件后确保文件-> 使缓存无效/重新启动。这对我有用。

    【讨论】:

    • 不幸的是它对我不起作用。我的目标是 1.4.30 - 项目和 AS 插件,AS 版本。 4.1.2.缓存失效后,还是同样的问题。
    【解决方案6】:

    改变这一行: 导入 kotlinx.parcelize.Parcelize 到: 导入 kotlinx.android.parcel.Parcelize

    【讨论】:

    • 但这已被弃用!这是迁移的重点
    猜你喜欢
    • 2021-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-25
    • 2021-12-26
    • 1970-01-01
    • 2019-11-28
    相关资源
    最近更新 更多