Olá! Meu nome é Kirill Rozov. Eu sou o autor do canal Telegram Android Broadcast . Eu amo muito o Kotlin e gosto de usar seus recursos para simplificar o desenvolvimento. Recentemente, enfrentei esse problema quando eles começaram a usar o View Binding em um novo projeto Android .

Esse recurso apareceu no Android Studio 3.6, mas na verdade não é totalmente novo, mas uma versão leve do Android Data Binding . Por que tantas complicações? O problema era a velocidade - muitos desenvolvedores usavam Android Data Binding
apenas para gerar código com links para o View e ignoravam os outros recursos da biblioteca. Para acelerar a geração de código, criado View Binding
. No entanto, a maneira padrão de trabalhar com isso é duplicar o código do qual você deseja se livrar.
A maneira padrão de trabalhar com o View Binding
Vamos dar uma olhada em View Binding usando o exemplo Fragment. Temos um recurso de layout com um nome profile.xml
(seu conteúdo não importa). Se quisermos usar o ViewBinding, na versão padrão será assim:
class ProfileFragment : Fragment(R.layout.profile) {
private var viewBinding: ProfileBinding? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewBinding = ProfileBinding.bind(view)
}
override fun onDestroyView() {
super.onDestroyView()
viewBinding = null
}
}
Existem vários problemas aqui:
- Muito código extra
- : Fragment
- Property
viewBinding
nullable .
C Kotlin
Kotlin Delegated Property
property Kotlin . , ViewBinding
. , ViewBinding
:
class FragmentViewBindingProperty<T : ViewBinding>(
private val viewBinder: ViewBinder<T>
) : ReadOnlyProperty<Fragment, T> {
internal var viewBinding: T? = null
private val lifecycleObserver = BindingLifecycleObserver()
@MainThread
override fun getValue(thisRef: Fragment, property: KProperty<*>): T {
checkIsMainThread()
this.viewBinding?.let { return it }
val view = thisRef.requireView()
thisRef.viewLifecycleOwner.lifecycle.addObserver(lifecycleObserver)
return viewBinder.bind(view).also { vb -> this.viewBinding = vb }
}
private inner class BindingLifecycleObserver : DefaultLifecycleObserver {
@MainThread
override fun onDestroy(owner: LifecycleOwner) {
owner.lifecycle.removeObserver(this)
viewBinding = null
}
}
}
-, :
inline fun <reified T : ViewBinding> Fragment.viewBinding(): ReadOnlyProperty<Fragment, T> {
return FragmentViewBindingProperty(DefaultViewBinder(T::class.java))
}
:
class ProfileFragment() : Fragment(R.layout.profile) {
private val viewBinding: ProfileBinding by viewBinding()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
}
, , . ?
, - ...
- View :
class ProfileFragment() : Fragment(R.layout.profile) {
private val viewBinding: ProfileBinding by viewBinding()
override fun onDestroyView() {
super.onDestroyView()
}
}
, ViewBinding property . super.onDestroyView()
. Fragment.viewLifecycleOwner
.
ON_DESTROY
Fragment.viewLifecycleOwner
Fragment.onDestroyView()
, FragmentViewBindingProperty
, . . , Handler
:
class FragmentViewBindingProperty<T : ViewBinding>(...) : ReadOnlyProperty<Fragment, T> {
internal var viewBinding: T? = null
private inner class BindingLifecycleObserver : DefaultLifecycleObserver {
private val mainHandler = Handler(Looper.getMainLooper())
@MainThread
override fun onDestroy(owner: LifecycleOwner) {
owner.lifecycle.removeObserver(this)
mainHandler.post { viewBinding = null }
}
}
}
.