这是我之前提到的question的后续内容。我正在使用https://github.com/nekocode/android-parcelable-intellij-plugin-kotlin中的Android Parcelable插件 根据bennyl的建议,我将构造函数的生成代码更改为
class ChessClock(context:Context) : TextView(context), Parcelable {
lateinit var player:String
constructor(context:Context, p:String, angle:Float) : this(context) {
player = p
rotation = angle
}
}
这解决了我所提出的语法错误。我现在有另一个我最初忽略的问题。
该插件为writeToParcel
生成了此代码:
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(player)
parcel.writeFloat(rotation)
parcel.writeLong(mTime)
parcel.writeInt(mState)
}
和这个构造函数:
constructor(parcel: Parcel) :this() {
player = parcel.readString()
rotation = parcel.readFloat()
mTime = parcel.readLong()
mState = parcel.readInt()
}
(实际上,我添加了旋转线,但这并不重要。)
现在,构造函数将无法编译。 this
有下划线,我看到了工具提示
我希望看到类似的东西,
constructor(parcel: Parcel) :this(context, parcel.readString(), parcel.readFloat()) {
mTime = parcel.readLong()
mState = parcel.readInt()
}
但如果我尝试了,我会收到消息,“在调用超类构造函数之前无法访问上下文。”我对kotlin(和android)很新,我不明白这里发生了什么。我试过调用super
,但它告诉我预期会调用主构造函数。我也试过调用TextView(),但它告诉我预期会调用this
或super
。
我没有看到有办法将上下文写入地块,(我不确定这意味着什么。)
你能告诉我代码应该如何修改,更重要的是,你能解释一下原因吗?
答案 0 :(得分:1)
context
才能调用this(context,...)
构造函数。但是,您无法将constructor(parcel: Parcel)
更改为constructor(context: Context, parcel: Parcel)
,因为Parcelable需要`构造函数(parcel:Parcel)
发生了什么事?您的类派生自TextView
,需要Context
来实例化。您的主要constructor
正在这样做......
class ChessClock(context: Context) : TextView(context) ...
文件说......
如果类具有主构造函数,则可以(并且必须)使用主构造函数的参数在那里初始化基类型。
由于您选择使用主构造函数,因此必须由该构造函数初始化基类,并且辅助构造函数链接到主构造函数。
constructor(context:Context, p:String, angle:Float) : this(context) ...
// notice how the secondary constructor has the context with which to
// call the primary constructor
您看到的错误是由于第二个辅助构造函数没有向它正在调用的构造函数提供上下文(它正在调用第一个辅助构造函数)。
constructor(parcel: Parcel) :this(context, parcel.readString(), parcel.readFloat()) ...
// compiler error because "context" has no source, there is no
// parameter "context" being supplied
更重要的是,Parcelable插件工具在向继承(see the example of a Parcelable implementation)添加Parcel
接口时添加了Parcelable
构造函数。因此,CREATOR
方法(必需的Parcelable.Creator
接口)期望找到仅占用Parcel
的构造函数。您可能需要调整设计,因为Context
不可序列化,因此不应该(不能)放在Parcel
中。您可以查看CREATOR
代码并查看有关修改的内容,但我建议您更改设计。
“最佳实践”是将业务逻辑与UI逻辑分开。在这里,您已将ChessClock
绑定到UI对象TextView
。一个“ChessClock”听起来像UI,所以也许你需要一个ChessClockData类来传递Parcelable
而不是时钟UI。