@CallSuper注解的坑
1.假如你写了一个gradle的库叫appFramework,这里面有个类BaseFragment继承了Fragment,而Fragment的onCreate方法使用了@CallSuper注解,这时候你的AFragment继承BaseFragment,如果你的项目是依赖appFramework的二进制,那么你的AFragment.onCreate会报Overriding method should call super.onCreate,虽然你已经调用了super.onCreate(),这不影响编译和运行。如果你的项目是直接依赖appFramework源码,那么不会报上面的错误。
留意!!操作符
val l = b!!.length
如果b为空就会抛一个NPE异常,看下面的java代码:
private Drawable clearTextIcon;
...
clearTextIcon = wrappedDrawable;
clearTextIcon.setBounds(0, 0, clearTextIcon.getIntrinsicHeight(), clearTextIcon.getIntrinsicHeight());
插件转换后的代码
private var clearTextIcon: Drawable? = null
...
clearTextIcon = wrappedDrawable
clearTextIcon!!.setBounds(0, 0, clearTextIcon!!.intrinsicHeight, clearTextIcon!!.intrinsicHeight)
注意如果这里的clearTextIcon为空了,就会抛出NPE,所以请谨慎使用!!,应该改成下面的代码
private var clearTextIcon: Drawable? = null
...
clearTextIcon = wrappedDrawable
val _clearTextIcon = clearTextIcon
_clearTextIcon?.setBounds(0, 0, _clearTextIcon?.intrinsicHeight, _clearTextIcon?.intrinsicHeight)
再来看一个栗子
java源码
if (onFocusChangeListener != null) {
onFocusChangeListener.onFocusChange(view, hasFocus);
}
插件转换后的代码:
if (onFocusChangeListener != null) {
onFocusChangeListener!!.onFocusChange(view, hasFocus)
}
上面的代码片段是非常丑陋的,应该改成下面简洁的方式:
onFocusChangeListener?.onFocusChange(view, hasFocus)
?:操作符的使用
java源码:
@Override
public boolean onTouch(final View view, final MotionEvent motionEvent) {
...
return onTouchListener != null && onTouchListener.onTouch(view, motionEvent);
}
插件转换后的代码:
override fun onTouch(view: View, motionEvent: MotionEvent): Boolean {
...
return onTouchListener != null && onTouchListener!!.onTouch(view, motionEvent)
}
可以改成下面的代码:
override fun onTouch(view: View, motionEvent: MotionEvent): Boolean {
...
return onTouchListener?.onTouch(view, motionEvent) ?: false
}
上面的代码的意思是如果onTouchListener不为null, 则调用onTouch方法,否则返回false。
as?的使用
java源码:
protected YtxTitle initYtxTitle() {
View titleView = findViewById(getResources().getIdentifier("ytx_title", "id", getPackageName()));
if (titleView != null && (titleView instanceof YtxTitle)) {
return (YtxTitle) titleView;
}
return null;
}
转换后的代码:
protected fun initYtxTitle(): YtxTitle? {
val titleView = findViewById(resources.getIdentifier("ytx_title", "id", packageName))
if (titleView != null && titleView is YtxTitle) {
return titleView
}
return null
}
应该改成下面的代码:
protected fun initYtxTitle(): YtxTitle? {
return findViewById(resources.getIdentifier("ytx_title", "id", packageName)) as? YtxTitle
}
a?是安全的类型转换,如果尝试转换不成功则返回null
== 和 ===的区别
kotlin有两种相等性:
- 引用相等(两个对象指向同一个对象)
应用相等由===(其否定形式!==)操作符判断,a===b
当且仅当a
和b
指向同一个对象时求值为true - 结构相等(用equals()检查)
结构相等由 == (其否定形式 != )操作判断。按照惯例,像 a == b 这样的表达式会 翻译成:
a?.equals(b) ?: (b === null)
a == null
会被自动转换为a === null