问题描述
这是我先前问的问题的后续内容.我正在使用 https://github.com/nekocode/android-parcelable-intellij-plugin-kotlin 按照bennyl的建议,我将为构造函数生成的代码更改为
This is a followup to a question I asked earlier. I am using the Android Parcelable plugin from https://github.com/nekocode/android-parcelable-intellij-plugin-kotlinFollowing bennyl's suggestion, I changed the generated code for the constructors to
class ChessClock(context:Context) : TextView(context), Parcelable {
lateinit var player:String
constructor(context:Context, p:String, angle:Float) : this(context) {
player = p
rotation = angle
}
}
,这摆脱了我所问过的语法错误.现在,我遇到了另一个我首先忽略的问题.
and this got rid of the syntax errors I had asked about. I now have another problem that I overlooked at first.
插件为writeToParcel
生成了以下代码:
The plugin generated this code for 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()
}
(实际上,我添加了带有旋转的行,但这并不重要.)
(Actually, I added the lines with rotation, but that's unimportant.)
现在,构造函数将无法编译. this
带下划线,我看到工具提示我希望看到类似
Now, the constructor won't compile. this
is underlined and I see the tooltipI would expect to see something like,
constructor(parcel: Parcel) :this(context, parcel.readString(), parcel.readFloat()) {
mTime = parcel.readLong()
mState = parcel.readInt()
}
但是,如果我尝试这样做,则会收到消息在调用超类构造函数之前无法访问上下文".我对Kotlin(和android)很陌生,我不明白这里发生了什么.我试过调用super
,但是它告诉我应该调用主构造函数.我还尝试了调用TextView(),但它告诉我应该调用this
或super
.
but if I try that, I get the message, "Cannot access context before superclass constructor has been called." I'm pretty new to kotlin (and android) and I don't understand what's happening here. I've tried invoking super
, but it tells me that a call to the primary constructor is expected. I've also tried invoking TextView() but it tells me that a call to this
or super
is expected.
我看不到有一种将上下文写入包裹的方法,(我不确定这是什么意思.)
I don't see that there is a way to write the context to the parcel, (and I'm not sure what this would mean.)
可以告诉我如何修改代码,更重要的是,您可以解释原因吗?
Can you tell me how the code should be modified, and more important, can you explain why?
推荐答案
context
以便调用this(context,...)
构造函数.但是,您不能将constructor(parcel: Parcel)
更改为constructor(context: Context, parcel: Parcel)
,因为Parcelable需要`constructor(parcel:Parcel)
context
needs to be supplied in order to call the this(context,...)
constructors. But, you cannot change your constructor(parcel: Parcel)
to constructor(context: Context, parcel: Parcel)
because Parcelable requires the `constructor(parcel: Parcel)
这是怎么回事?您的类是从TextView
派生的,它需要Context
进行实例化.您的主要constructor
正在这样做...
What's going on? Your class derives from TextView
which requires a Context
to instantiate. Your primary constructor
is doing that...
class ChessClock(context: Context) : TextView(context) ...
文档说...
由于已选择使用主构造函数,因此必须由该构造函数初始化基类,并且将辅助构造函数链接到主构造函数.
Since you've chosen to use a primary constructor, the base class must be initialized by that constructor, and the secondary constructors chain off of the primary.
constructor(context:Context, p:String, angle:Float) : this(context) ...
// notice how the secondary constructor has the context with which to
// call the primary constructor
您看到的错误是由于第二个辅助构造函数未向其正在调用的构造函数提供上下文(正在调用第一个辅助构造函数).
The error you are seeing is due to the second secondary constructor not supplying a context to the constructor that it is calling (it's calling the first secondary 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
接口添加到继承中时,Parcelable插件工具添加了Parcel
构造函数(请参阅Parcelable实现的示例).因此,CREATOR
方法(必需的Parcelable.Creator
接口)期望找到仅采用Parcel
的构造函数.您可能必须调整设计,因为Context
不可序列化,因此不应(不能)放置在Parcel
中.您可以查看CREATOR
代码并查看有关对其进行修改的信息,但我建议您进行设计更改.
More importantly, the Parcel
constructor was added by the Parcelable Plug-in tool when it added Parcelable
Interface to the inheritance (see the example of a Parcelable implementation). And as such, the CREATOR
method (the required Parcelable.Creator
Interface) expects to find a constructor that takes only a Parcel
. You may have to adjust your design, because a Context
is not serializable and therefore should not (cannot) be placed in a Parcel
. You could look at the CREATOR
code and see about modifying that, but I would recommend a design change.
最佳做法"是将业务逻辑与UI逻辑分开.在这里,您已将ChessClock
绑定到UI对象TextView
.在我看来,"ChessClock"听起来像UI,所以也许您需要一个ChessClockData类作为Parcelable
而不是Clock UI来传递.
"Best practice" is to separate your business logic from your UI logic. Here you have tied your ChessClock
to a UI object TextView
. A "ChessClock" sound to me like UI, so maybe you need a ChessClockData class to pass around as a Parcelable
instead of the Clock UI.
这篇关于在Kotlin派生类中采用可组装构造函数的构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!