创建自定义视图时,我注意到许多人似乎这样做:
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和代码很好地创建视图,但我不确定这种方法是否有任何缺点。这会在所有情况下都有效吗?
答案 0 :(得分:4)
从我的回答中复制了类似的问题。
如果覆盖所有三个构造函数,请不要CASCADE this(...)
CALLS。你应该这样做:
public MyView(Context context) {
super(context);
init(context, null, 0);
}
public MyView(Context context, AttributeSet attrs) {
super(context,attrs);
init(context, attrs, 0);
}
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
// do additional work
}
原因是父类可能在其自己的构造函数中包含您可能意外覆盖的默认属性。例如,这是TextView
:
public TextView(Context context) {
this(context, null);
}
public TextView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, com.android.internal.R.attr.textViewStyle);
}
public TextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
如果您没有致电super(context)
,则无法将R.attr.textViewStyle
正确设置为样式attr。
答案 1 :(得分:-2)
是的,这是一个合理的模式,因此不必须在每个构造函数中重复自定义工作。不,该方法似乎没有任何缺点。
答案 2 :(得分:-2)
这纯粹取决于你的要求。让我们说如果你想在父类中使用任何方法而不在自定义视图中覆盖它们的功能,那么你需要使用super()和实例化父类。如果您不需要在父类中调用任何方法,则在自定义视图中覆盖所有实现,然后您不需要。阅读此link中的自定义视图示例部分。
答案 3 :(得分:-5)