as插件java转kotlin遇到的坑

@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 当且仅当 ab 指向同一个对象时求值为true
  • 结构相等(用equals()检查)
    结构相等由 == (其否定形式 != )操作判断。按照惯例,像 a == b 这样的表达式会 翻译成:
a?.equals(b) ?: (b === null)

a == null 会被自动转换为 a === null

你可能感兴趣的:(as插件java转kotlin遇到的坑)