都2202了,当然不是去findById。
至于是viewbinding还是databinding,各有所爱。
android {
...
buildFeatures {
// 使用dataBinding
dataBinding = true
// 使用 view binding :
viewBinding = true
}
...
}
通常来说,我们开启viewbinding之后,最原始的方式,是这样使用的。
class MainActivity : AppCompatActivity() {
private lateinit var binding : ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
}
}
是的,每一个Activity都去蒸腾一下bind,是挺麻烦的。
封装方式千千万,这里说几种。
无脑图省事 三方开源ViewBindingKTX
// viewbind 封装base https://github.com/DylanCaiCoding/ViewBindingKTX/blob/master/README_ZH.md
implementation 'com.github.DylanCaiCoding.ViewBindingKTX:viewbinding-ktx:2.1.0'
implementation 'com.github.DylanCaiCoding.ViewBindingKTX:viewbinding-nonreflection-ktx:2.1.0'
implementation 'com.github.DylanCaiCoding.ViewBindingKTX:viewbinding-base:2.1.0'
implementation 'com.github.DylanCaiCoding.ViewBindingKTX:viewbinding-brvah:2.1.0'
支持BaseActivity,BaseFragment,也知道dadpter ,可结合brvah
然后
BaseBindingActivity
abstract class BaseBindingActivity<VB : ViewBinding> : AppCompatActivity(),
ActivityBinding<VB> by ActivityBindingDelegate() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentViewWithBinding()
}
fun startActivity(targetCls: Class<*>) = startActivity(Intent(this, targetCls))
}
BaseBindingFragment
abstract class BaseBindingFragment<VB : ViewBinding> : Fragment(),
FragmentBinding<VB> by FragmentBindingDelegate() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return createViewWithBinding(inflater, container)
}
}
使用一下
class MainActivity : BaseBindingActivity<ActivityMainBinding>() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding.tvLog.text ="123"
}
}
这样,真的简单了很多很多。
每次只要声明有一下 xxxxbinding就好,而且,只需要1次。
比很多常见的封装,使用起来清爽很多了。
databind的封装
首先拓展一下Activity
/**
* Activity中使用DataBinding时setContentView的简化
* [layout] 布局文件
* @return 返回一个Binding的对象实例
*/
fun <T : ViewDataBinding> Activity.bindView(@LayoutRes layout: Int): T {
return DataBindingUtil.setContentView(this, layout)
}
/**
* Activity中使用DataBinding时setContentView的简化
* [layout] 布局文件
* @return 返回一个Binding的对象实例 T 类型的 可null的
*/
fun <T : ViewDataBinding> Activity.bindView(view: View): T? {
return DataBindingUtil.bind<T>(view)
}
/**
* 界面Activity的沉浸式状态栏,使得可以在状态栏里面显示部分需要的图片
* 注意点,需要在setContentView之前调用该函数才生效
*/
fun Activity.immediateStatusBar() {
window.apply {
addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN)
addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
decorView.systemUiVisibility =
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
}
}
/**
* 软键盘的隐藏
* [view] 事件控件View
*/
fun Activity.dismissKeyBoard(view: View) {
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager?
imm?.hideSoftInputFromWindow(view.windowToken, 0)
}
//endregion
//region 扩展属性
/**
* 扩展lifeCycleOwner属性,便于和Fragment之间使用lifeCycleOwner 一致性
*/
val ComponentActivity.viewLifeCycleOwner: LifecycleOwner
get() = this
/**
* Activity的扩展字段,便于和Fragment中使用liveData之类的时候,参数一致性
*/
val Activity.context: Context
get() = this
//endregion
BaseActivity
abstract class BaseActivity<ActBinding : ViewDataBinding> : AppCompatActivity {
/**
* 无参构造函数
*/
constructor() : super()
/**
* 可以填入layout布局的构造函数,使用viewBinding的方便
* [layout] layout布局文件的id
*/
constructor(@LayoutRes layout: Int) : super(layout)
protected lateinit var mBinding: ActBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mBinding = bindView<ActBinding>(getLayoutRes()).also {
it.lifecycleOwner = viewLifeCycleOwner
}
initView()
initConfig()
initData()
}
@LayoutRes
abstract fun getLayoutRes(): Int
/**
* 必要的view初始化
*/
open fun initView() {
// LogUtils.d("${this.javaClass.simpleName} 初始化 initView")
}
/**
* 必要的配置初始化
*/
open fun initConfig() {
// LogUtils.d("${this.javaClass.simpleName} 初始化 initConfig")
}
/**
* 必要的数据初始化
*/
open fun initData() {
// LogUtils.d("${this.javaClass.simpleName} 初始化 initData")
}
override fun onDestroy() {
super.onDestroy()
if (this::mBinding.isInitialized) {
mBinding.unbind()
}
}
/**
* 扩展用于liveData便捷写法的函数
* [block]liveData对象,响应change变化的逻辑块
*/
protected inline fun <T : Any> LiveData<T>.observeKt(crossinline block: (T?) -> Unit) {
this.observe(this@BaseActivity, Observer {
block(it)
})
}
}
BaseFragment
abstract class BaseFragment : Fragment {
/**
* 无参构造函数
*/
constructor() : super()
/**
* 可以填入layout布局的构造函数,使用viewBinding的方便
* [layout] layout布局文件的id
*/
constructor(@LayoutRes layout: Int) : super(layout)
//UI的viewDataBinding对象
private var mBinding: ViewDataBinding? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(getLayoutRes(), container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mBinding = bindView(view, savedInstanceState)
mBinding?.lifecycleOwner = viewLifecycleOwner
initConfig()
initData()
}
@LayoutRes
abstract fun getLayoutRes(): Int
abstract fun bindView(view: View, savedInstanceState: Bundle?): ViewDataBinding
/**
* view初始化后的必要配置
*/
open fun initConfig() {
// LogUtils.d("${this.javaClass.simpleName} 初始化 initConfig")
}
/**
* view初始化后的必要数据
*/
open fun initData() {
// LogUtils.d("${this.javaClass.simpleName} 初始化 initData")
}
override fun onDestroy() {
super.onDestroy()
mBinding?.unbind()
}
/**
* 扩展用于liveData便捷写法的函数
* [block]liveData对象,响应change变化的逻辑块
*/
protected fun <T : Any> LiveData<T>.observeKt(block: (T?) -> Unit) {
this.observe(viewLifecycleOwner, Observer {
block(it)
})
}
}
使用一下
class MainActivity : BaseActivity<ActivityMainBinding>() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mBinding.tvLog
}
override fun getLayoutRes() = R.layout.activity_main
}