对于 android 自定义视图构造函数,我应该调用 super() 还是调用 this() ?
创建自定义视图时,我注意到很多人似乎都是这样做的:
public MyView(Context context) {
super(context);
// this constructor used when programmatically creating view
doAdditionalConstructorWork();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// this constructor used when creating view through XML
doAdditionalConstructorWork();
}
private void doAdditionalConstructorWork() {
// init variables etc.
}
我的问题是它阻止我将变量设为最终值。有什么理由不做以下事情?
public MyView(Context context) {
this(context, null);
// this constructor used when programmatically creating view
}
public MyView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
// this constructor used when creating view through XML
}
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// this constructor used where?
// init variables
}
我已经能够通过 XML 和代码很好地创建视图,但我不确定这种方法是否有任何缺点。这在所有情况下都有效吗?
When creating a custom view, I have noticed that many people seem to do it like this:
public MyView(Context context) {
super(context);
// this constructor used when programmatically creating view
doAdditionalConstructorWork();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// this constructor used when creating view through XML
doAdditionalConstructorWork();
}
private void doAdditionalConstructorWork() {
// init variables etc.
}
My problem with this is that it stops me from making my variables final. Any reason not to do the following?
public MyView(Context context) {
this(context, null);
// this constructor used when programmatically creating view
}
public MyView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
// this constructor used when creating view through XML
}
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// this constructor used where?
// init variables
}
I've been able to create the view just fine through XML and through code, but I'm not sure if there are any drawbacks to this approach. Will this work in all cases?
There is another part to this question
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
编辑:
这不行。查看此问题的其他答案以了解原因。
原答案:
可以。
当我们查看
TextView.java
。他们使用相同的层次结构。
所以你可以接受这种方法。
Edit:
This is not Okay. See other answers to this question for reasons.
Original Answer:
It is Ok.
When we look at the source of
TextView.java
.They have used the same hierarchy.
So you are Okay with this approach.
我看到的唯一缺点(似乎没有人提到)是你的第二个构造函数丢失了超类的 defStyle ,因为你将它设置为零。查看任意 Android View 类的源代码,您会发现第二个构造函数始终定义了特定的
defStyle
。例如,这是 ListView 的第二个构造函数:
如果您要使用您描述的第二种方法扩展 ListView,则
com.android.internal.R.attr.listViewStyle
将不再是defStyle
,因为您将绕过第二个超级构造函数并将其设置为零。我想你可以通过使用与 ListView 相同的defstyle
来解决这个问题,如下所示:但这并不完全是“纯粹”的方式,因为你人为地强迫它具有相同的
defStyle< /代码> 作为列表视图。
因此,与其他人所说的相反,我实际上认为您最好使用帖子中概述的第一个
doAdditionalConstructorWork()
方法,因为这至少可以确保defStyle 设置正确。
The only drawback I can see (that no one seems to have mentioned) is that your second constructor loses the
defStyle
of the superclass, because you set it to zero. Look at the source code for any of Android's View classes, and you'll notice that the second constructor always has a specificdefStyle
defined.For example, this is the second constructor of ListView:
If you were to extend ListView using the second approach that you describe,
com.android.internal.R.attr.listViewStyle
would no longer be thedefStyle
, because you'd be bypassing that second super constructor and making it zero instead. I suppose you could resolve this by using the samedefstyle
as ListView, like so:But it's not exactly the "purist" way, because you're artificially forcing it to have the same
defStyle
as ListView.So, contrary to what the others said, I actually think you're better off using the first
doAdditionalConstructorWork()
approach outlined in your post, because that at least makes sure that thedefStyle
is set correctly.从我对类似问题的回答中复制了此内容。
如果您重写所有三个构造函数,请不要级联
this(...)
调用。相反,您应该这样做:原因是父类可能在其自己的构造函数中包含默认属性,您可能会意外覆盖这些默认属性。例如,这是
TextView
的构造函数:如果您没有调用
super(context)
,则无法正确设置R.attr.textViewStyle 作为样式属性。
Copied this from my answer for a similar question.
If you override all three constructors, please DO NOT CASCADE
this(...)
CALLS. You should instead be doing this:The reason is that the parent class might include default attributes in its own constructors that you might be accidentally overriding. For example, this is the constructor for
TextView
:If you did not call
super(context)
, you would not have properly setR.attr.textViewStyle
as the style attr.是的,这是一种合理的使用模式,因此您不必在每个构造函数中重复自定义工作。不,该方法似乎没有任何缺点。
Yup, that's a reasonable pattern to use so you don't have to repeat the custom work in every one of your constructors. And no, there don't appear to be any drawbacks to the method.
这完全取决于您的要求。假设您想使用父类中的任何方法而不覆盖自定义视图中的功能,那么您需要使用 super() 并实例化父类。如果您不需要调用父类中的任何方法,那么您就不需要在自定义视图中重写所有实现。阅读此中的自定义视图示例部分链接。
It purely depends on your requirement. Let us say if you want to use any methods in parent class without overriding their functionality in your custom view, then you need to use super() and instantiate parent class. If you dont need to invoke any methods in parent class all implementations are overridden in your custom view, then you don't need. Read A custom View Example section in this link.