【问题标题】:@Parcelize annotation toghether with inheritance@Parcelize 注解和继承
【发布时间】:2018-01-04 14:31:37
【问题描述】:

我无法使用@parcelize 注释创建通用结构。 我希望构造函数用作 Jason、Room 和 Parcelable 的构造函数。

假设我们有课

@Parcelize
class Food(var taste: String = "")

现在首先想到两个解决方案

1.抱怨口味必须是 var 或 val,才有可用的 Parceable 构造函数

@Parcelize
class FastFood(var callory:String = "", taste: String): Food(taste) // error

2.抱怨我必须明确地忽略口味 - 那么多态性有什么好处?

@Parcelize
class FastFood(var callory: String = "", var taste: String): Food(taste) // error

如何将继承与您的库一起有效地使用?

【问题讨论】:

    标签: android kotlin parcelable


    【解决方案1】:

    在 Kotlin 中,如果您在构造函数 'val' 或 'var' 中添加值,它就会成为类属性。要使用 Parceable,您需要添加它,因为没有它 Parcelable.Creator 无法访问它。然后你需要在 Food 类和属性 'taste' 中添加 'open' 修饰符,因为在 Kotlin 中默认情况下都是 final,所以你将能够覆盖味觉值。

    @Parcelize
    open class Food(open val taste: String)
    
    @Parcelize
    class FastFood(var callory:String = "", override val taste: String): Food(taste)
    

    【讨论】:

    • 这样我给味道分配了两次价值,我说得对吗?我知道语法是正确的,它似乎是一些 kotlin 缺陷
    • 是的,Food 和 FastFood 都将包含带有“taste”的属性。您可以从 FastFood 中删除属性 'taste',但在这种情况下,您应该拒绝注释 @Parcelize 并自行完成
    • 您的解决方案将不起作用。关于这个问题有一个未解决的问题:youtrack.jetbrains.com/issue/KT-22139
    【解决方案2】:

    我一直无法使用@Parcelize 找到完美的解决方案,但有两种方式略有缺陷。

    1) 将基类抽象化,并且只在子类中使用@Parcelize。这意味着您不能拥有父级的实例,但有时这很好。如果你能负担得起,这是一个有效的解决方案。

    abstract class Food : Parcelable {
        abstract var taste: String
    }
    
    @Parcelize
    class FastFood(var callory: String = "", override var taste: String = "") : Food()
    

    2) 也许您需要能够创建父级的实例。一种方法是使基类不是父类,而是父类和子类的父类。不幸的是,这稍微打乱了类的层次结构,并且 FastFood 将不是一种 Food,而是两者都将是一种 BaseFood。

    abstract class BaseFood : Parcelable {
        abstract var taste: String
    }
    
    @Parcelize
    class Food(override var taste: String = "") : BaseFood()
    
    @Parcelize
    class FastFood(var callory: String = "", override var taste: String = "") : BaseFood()
    

    【讨论】:

      【解决方案3】:

      截至 2021 年 12 月,问题仍然存在,我无法通过 @Parcelize 使用继承

      父类:

      import android.os.Parcelable
      import kotlinx.parcelize.Parcelize
      
      @Parcelize
      open class Parent (
          var parentString : String
      ) : Parcelable {
          constructor(): this("")
      }
      

      子类(继承父类)

      import android.os.Parcelable
      import kotlinx.parcelize.Parcelize
      
      @Parcelize
      data class Child (
          var childString : String
      ) : Parent(), Parcelable {
          constructor() : this("")
      }
      

      我将子类对象从 ActivityA 发送到 ActivityB

      ActivityA 代码:(发件人)

      val child = Child()
      child.childString = "THIS IS CHILD"
      child.parentString = "THIS IS PARENT"
      val intent = Intent(this, ActivityB::class.java)
      val bundle = Bundle()
      bundle.putParcelable("parcel", child)
      intent.putExtra("bundle", bundle)
      startActivity(intent)
      

      ActivityB 代码:(接收者)

      val bundle = intent.getBundleExtra("bundle")
      val child = bundle?.getParcelable<Child>("parcel") as Child
      Log.e("Child Class c", child.childString) //THIS IS CHILD
      Log.e("Parent Class p", child.parentString) //"" <- issue
      

      child.parentString = "",而不是 THIS IS PARENT,这是 @Parcelize

      的问题

      【讨论】:

        猜你喜欢
        • 2011-03-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-02
        • 2015-08-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多