听来不错,因此我们经常将这些构造函数:
class CustomLinearLayout : LinearLayout {
constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
}
合并成一个构造函数:
class CustomLinearLayout @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr)
我们先来看看Design
库中的TextInputEditText
控件,
在我们自定义类中,如下:
class CustomTextInputEditText : TextInputEditText {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
}
上面的代码可以通过一个构造函数来替换:
class CustomTextInputEditText @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : TextInputEditTe
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
xt(context, attrs, defStyleAttr)
这也是Android Studio 会自动为我们生成的代码
!](https://upload-images.jianshu.io/upload_images/15679108-d208f39b8eb1877c?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
接下来我们写一个Activity,它有两个CustomTextInputEditText
控件,第一个包含所有三个构造函数,第二个包含 @JvmOverloads
注释。
class CustomTextInputEditText1 : TextInputEditText {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
}
class CustomTextInputEditText2 @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : TextInputEditText(context, attrs, defStyleAttr)
它们的表现最终会相同吗?
[外链图片转存失败(img-jtjcLWwA-1569229719416)(https://upload-images.jianshu.io/upload_images/15679108-f64a5b1fa110e916?imageMogr2/auto-orient/strip)]
正如你所看到的,第二个使用@JvmOverloads
注解的控件没有工作。
发生了什么?为什么会有一些样式问题?
[外链图片转存失败(img-NBnEi2L8-1569229719418)(https://upload-images.jianshu.io/upload_images/15679108-0b77b50c7a77c58b?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]
让我们再花1秒钟回看一下JvmOverloads
的定义,我们知道Kotlin编译器会产生两个重载(在我们的例子中N = 3
和M = 2
)。所以我们最终会得到三个类似的构造函数:
@JvmOverloads
public CustomTextInputEditText(@NotNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@JvmOverloads
public CustomTextInputEditText(@NotNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
@JvmOverloads
public CustomTextInputEditText(@NotNull Context context) {
this(context, null, 0);
}
因此在我们的自定义类中,我们总是会调用到CustomTextInputEditText
三参数构造函数。
现在让我们暂时关注到View的构造函数。
当View从XML文件中加载时,会调用其第二个构造函数。然后,此构造函数调用三参数构造函数。
public View(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
如果通常将0
作为第三个参数,为什么这个三参数构造函数要存在呢?答案在文档中。
View的这个构造函数允许子类在加载时使用它们自己的基本样式。
继承自View的类可以传递它们自己的样式来修改所有基本view
属性。
简单,现在我们来看看为什么会出错。