Rendre Android View Binding pratique avec Kotlin

salut! Je m'appelle Kirill Rozov. Je suis l'auteur de la chaîne Telegram Android Broadcast . J'aime beaucoup Kotlin et j'aime utiliser ses fonctionnalités pour simplifier le développement. J'ai récemment rencontré ce problème lorsqu'ils ont commencé à utiliser View Binding sur un nouveau projet Android .


image


Cette fonctionnalité est apparue dans Android Studio 3.6, mais en fait elle n'est pas entièrement nouvelle, mais une version allégée d' Android Data Binding . Pourquoi tant de complications? Le problème était la vitesse - de nombreux développeurs utilisaient Android Data Bindinguniquement pour générer du code avec des liens vers View et ignoraient les autres fonctionnalités de la bibliothèque. Pour accélérer la génération de code, créé View Binding. Cependant, la façon standard de travailler avec elle est de dupliquer le code dont vous voulez vous débarrasser.


La façon standard de travailler avec View Binding


Examinons la liaison de vues à l'aide de l'exemple Fragment. Nous avons une ressource de mise en page avec un nom profile.xml(son contenu n'a pas d'importance). Si nous voulons utiliser ViewBinding, alors dans la version standard, cela ressemblera à ceci:


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)
        //   viewBinding
    }

    override fun onDestroyView() {
        super.onDestroyView()
        viewBinding = null
    }
}

Il y a plusieurs problèmes ici:


  • Beaucoup de code supplémentaire
  • : 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)
        //   viewBinding
    }
}

, , . ?


, - ...


- View :


class ProfileFragment() : Fragment(R.layout.profile) {

    private val viewBinding: ProfileBinding by viewBinding()

    override fun onDestroyView() {
        super.onDestroyView()
        //  View  viewBinding
    }
}

, 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 }
        }
    }
}

.


All Articles