前言:
不得不说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}")
}