前言:
不得不說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
}
可以看到
- ActivityMainBinding是編譯器生成的
- 使用的androidx的包
- 沒有熟悉的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沒有了 是怎麼關聯佈局文件的呢?
查看源碼可以知道
- activity_main.xml文件已經被封裝到ActivityMainBinding 這個類裏面了
- inflate封裝的正是DataBindingUtil,也就是進一步簡化了代碼
- 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>
可以發現
- 第二種方法可避免編譯器未使用的警告
- 第三種方法則可以傳參
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}")
}