课程名称:移动端架构师
课程章节:Android必备Kotlin核心技术
课程讲师:CrazyCodeBoy LovelyChubby
课程内容:
使用 Kotlin 安卓扩展,向findViewById说拜拜
字符串的空判断,向TextUtils.isEmpty说拜拜
使用@JvmOverloads告别繁琐的构造函数重载
在进行Android 编码时我们避免不了的需要使用findViewById()
来获取指定控件的对象,下面是摘自我们的底部导航组件HiTabBottom.java
中的一段代码:
tabImageView = findViewById(R.id.iv_image); tabIconView = findViewById(R.id.tv_icon); tabNameView = findViewById(R.id.tv_name); groupView = findViewById(R.id.rl_root);
从上面代码中不难看出我们应用了大量的findViewById(R.id.xx)
的模板代码,那是否能有一种方式能帮我们减少这些重复劳动呢?
你能会想到JakeWharton大神的"黄油刀":
@BindView(R.id.iv_image) ImageView tabImageView;
虽然黄油刀能帮我们省去findViewById(R.id.xx)
的模板代码,但它还是需要我们使用@BindView(R.id.xxx)的这样的模块代码,那有没有一种方式能够使我们直接获取
xml中的控件而不用先获取在使用呢?
答案是有的。
在Kotlin中这些看似离谱的要求,也是可以实现的,Kotlin为Android开发者提供了安卓扩展,安卓扩展是 IntelliJ IDEA 与 Android Studio 的 Kotlin 插件的组成之一,因此不需要再单独安装额外插件。
我们仅需要在模块的 build.gradle
文件中启用 Gradle 安卓扩展插件即可:
apply plugin: 'kotlin-android-extensions'
仅需要一行即可非常方便导入指定布局文件中所有控件属性:
import kotlinx.android.synthetic.main.<布局>.*
因此,如果布局文件名是 hi_tab_bottom.xml
,我们将导入 kotlinx.android.synthetic.main.hi_tab_bottom.*
。
若需要调用 View 的合成属性,同时还应该导入 kotlinx.android.synthetic.main.hi_tab_bottom.view.*
。
导入完成后即可调用在xml文件中以视图控件具名属性的对应扩展,比如下例:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rl_root" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/iv_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@id/tv_name" android:layout_centerHorizontal="true" android:layout_marginBottom="4dp" android:scaleType="centerInside" android:visibility="gone" /> <TextView android:id="@+id/tv_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@id/tv_name" android:layout_centerHorizontal="true" android:layout_marginBottom="4dp" android:textColor="#666666" android:textSize="25dp" android:textStyle="bold" android:visibility="gone" /> <TextView android:id="@+id/tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="7dp" android:includeFontPadding="false" android:textColor="#999999" android:textSize="10dp" /> </RelativeLayout>
接下来我们就可以通过空间id来访问这些控件的实例了:
iv_image.visibility = View.GONE tv_icon.visibility = View.VISIBLE
在我们日常开发中,经常会对字符串进行空判断,相信大家对TextUtils.isEmpty
一定都不陌生,它可以帮我们判断字符串是否为空而且不用担心npe问题。
那么在Kotlin中,有一个叫:
public inline fun CharSequence?.isNullOrEmpty(): Boolean = this == null || this.length == 0
的扩展函数能帮我们省去对TextUtils.isEmpty
的使用:
Java
if (!TextUtils.isEmpty(tabInfo.name)) { tabNameView.setText(tabInfo.name); }
Kotlin
if (!tabInfo.name.isNullOrEmpty()) { tabNameView.text = tabInfo.name; }
除了isNullOrEmpty
扩展之外,CharSequence还有个名叫:
public inline fun CharSequence?.isNullOrBlank(): Boolean = this == null || this.isBlank()
如果 name 都是空格,则 TextUtils.isEmpty 不满足使用。那 isNullOrBlank 可用。
在Kotlin中@JvmOverloads注解的作用就是:在有默认参数值的方法中使用@JvmOverloads注解,则Kotlin就会暴露多个重载方法。
这对我们自定义控件时特别有用,不信你看:
Java
public class HiTabBottomLayout extends FrameLayout { ... public HiTabBottomLayout(@NonNull Context context) { this(context, null); } public HiTabBottomLayout(@NonNull Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public HiTabBottomLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } ...
Kotlin
class HiTabBottom @JvmOverloads constructor( context: Context?, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : RelativeLayout(context, attrs, defStyleAttr)
上面是摘自我们的底部导航组件HiTabBottom.java
中的一段代码,在用kotlin重写有,我们只需要在我们的主构造方法中使用@JvmOverloads
,便可以实现一个顶三个的效果是不是很不可思议呢。
课程收获:
谢谢老师,老师讲解细致,通俗易懂,这一节学习的是Kotlin的实用技巧,通过学习实用技巧可以大大节省代码量,节省编码时间,期待后边的继续学习。