直接引用布局 ID

    都知道,在 Kotlin 中可以不再使用繁琐的 findViewById(),而是可以直接调用布局 ID,例如:

    <TextView
        android:id=@+id/text_download
        android:layout_width=match_parent
        android:layout_height=wrap_content
        android:gravity=center_horizontal
        android:text=Download />

    在 Java 中你需要……

    TextView t_d = (TextView)findViewById(R.id.text_download);
    t_d.setText(daolnwoD);

    但是,在 Kotlin 中可以直接:

    text_download.text = daolnwoD

    但是这个地方有一个坑,就是不能在 onCreateView() 返回之前使用,不过这只有 Fragment 需要注意。

    打个比方,这是你的某一个 Fragment:

    class DeviceFragment : Fragment() {
    
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            val root = inflater.inflate(R.layout.fragment_device, container, false)
            return root
        }
    }

    加入这个时候,你要随着布局一起执行方法 setInfo(),你可能会这么做:

    (布局文件同上)

    class DeviceFragment : Fragment() {
    
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            val root = inflater.inflate(R.layout.fragment_device, container, false)
            setInfo()
            return root
        }
    
        fun setInfo(){
            text_download.text = daolnwoD
        }
    }

    看起来没有问题,但是运行时很可能会触发空指针

    java.lang.NullPointerException: Attempt to invoke virtual method \'……\' on a null object reference

    后来在 Rikka 的开发者群里问了才知道,Kotlinx 的 View 必须在 Fragment 的 onCreateView() 返回之后才能用

    也就是说,你需要这么改:

    class DeviceFragment : Fragment() {
    
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            val root = inflater.inflate(R.layout.fragment_device, container, false)
            return root
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            setInfo()
        }
    
        fun setInfo(){
            text_download.text = daolnwoD
        }
    }

    即,将方法放进 onViewCreated() 中执行。

    Databinding 中的 onClick

    类似 android:onLongClick="@{listener::onLongClick}" 在写对应的 onLongClick 的时候,需要写 Boolean 返回值,如:

    interface ItemListener {
        fun onLongClick(v: View): Boolean
    }

    然后我要写 onClick 的时候就理所当然的:

    interface ItemListener {
        fun onClick(v: View)
    : Boolean
        fun onLongClick(v: View): Boolean
    }

    结果是一直报错,提示找不到这个布局文件对应的 Impl 结尾的类。

    例如:databinding.ItemFileOrDirectoryBindingImpl

    闹了半天,是 onLongClick 需要 Boolean 返回值,但是 onClick 不用……

    interface ItemListener {
        fun onClick(v: View)
        fun onLongClick(v: View): Boolean
    }