新版Databinding基礎教程

前言:
不得不說AS更新到3.4後修復了一些隱藏的Bug並加入了一些新東西,如Bundle打包,DataBinding的寫法改動 等等,這些突然讓筆者覺得陌生,但歷史的車輪滾滾向前,沒辦法只能跟緊腳步,落後就只能被淘汰,這裏着重講一下Databinding改動後的一些寫法。

加入了generateStubs,不需要再引入databinding了
build_gradle寫法

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

android {
    ···
    defaultConfig {
  ·		  ···
    }
    
    dataBinding {
        enabled true
    }

}
kapt {
    generateStubs = true
}

可以看到

  1. ActivityMainBinding是編譯器生成的
  2. 使用的androidx的包
  3. 沒有熟悉的setContentView()了

Activity 用法

import androidx.appcompat.app.AppCompatActivity
import xxx.xxx.xxx.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(ActivityMainBinding.inflate(layoutInflater, null, false).root)
    }
}

Fragment 用法

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import xxx.xxx.xxx.databinding.FragmentNiceBinding

class NiceFragment : Fragment() {
    private lateinit var binding: FragmentNiceBinding
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        binding = FragmentNiceBinding.inflate(inflater, container, false)
        binding.setLifecycleOwner(viewLifecycleOwner)
        binding.executePendingBindings()
        return binding.root
    }
}

那麼有人會問:那setContentView沒有了 是怎麼關聯佈局文件的呢?
查看源碼可以知道

  1. activity_main.xml文件已經被封裝到ActivityMainBinding 這個類裏面了
  2. inflate封裝的正是DataBindingUtil,也就是進一步簡化了代碼
  3. ActivityMainBinding的名字也是根據activity_main來的
    因此你會發現無論
    ActivityxxxBinding inflate 到 xxxFragment
    還是
    FragmentxxxBinding inflate 到 xxxActivity
    都沒毛病

Activity的inflate

  @NonNull
  public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater,
      @Nullable ViewGroup root, boolean attachToRoot, @Nullable DataBindingComponent component) {
    return DataBindingUtil.<ActivityMainBinding>inflate(inflater, dae.rounder.R.layout.activity_main, root, attachToRoot, component);
  }

Fragment的inflate

  @NonNull
  public static FragmentPBinding inflate(@NonNull LayoutInflater inflater, @Nullable ViewGroup root,
      boolean attachToRoot, @Nullable DataBindingComponent component) {
    return DataBindingUtil.<FragmentPBinding>inflate(inflater, dae.rounder.R.layout.fragment_p, root, attachToRoot, component);
  }

剩下對之前文章的補充

onclick的三種寫法

<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <import type="xxx.MainViewModel"/>

        <variable
                name="mainViewModel"
                type="MainViewModel"/>
    </data>

    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:onClick="@{mainViewModel::expend}"
            android:orientation="vertical">
        <TextView android:layout_width="match_parent"
                  android:onClick="@{() -> mainViewModel.expend_()}"
                  android:layout_height="300dp" android:text="第一部分"/>
        <TextView android:layout_width="match_parent"
                  android:onClick="@{(v) -> mainViewModel.expend__(v)}"
                  android:layout_height="300dp" android:text="第二部分"/>
    </LinearLayout>
</layout>

可以發現

  1. 第二種方法可避免編譯器未使用的警告
  2. 第三種方法則可以傳參
    fun expend(v: View) {
        Timber.e("expend" + v::class.java.simpleName)
    }

    fun expend_() {
        Timber.e("expend_")
    }

    fun expend__(v: View) {
        Timber.e("expend__${(v as TextView).text}")
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章