androidkotlinandroid-databindingandroid-viewbinder

Databinding not work together with viewbinding in Kotlin


Android Studio 3.6

build.gradle:

buildscript {
    ext.kotlin_version = '1.3.50'
    repositories {
        google()
        jcenter()

    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.6.0-beta01'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

in app/build.gradle:

android {
    viewBinding.enabled = true
    dataBinding {
        enabled = true
    }

in my activity:

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.viewpager2.widget.ViewPager2

import com.myproject.BuildConfig
import com.myproject.R
import com.myproject.adapter.CustomFragmentStateAdapter
import com.myproject.databinding.QrBluetoothSwipeActivityBinding
import com.myproject.ui.fragment.BluetoothPageFragment
import com.myproject.ui.fragment.QrPageFragment
import androidx.databinding.DataBindingUtil
import androidx.databinding.ObservableInt

class QRBluetoothSwipeActivity : AppCompatActivity() {
    private lateinit var viewBinding: QrBluetoothSwipeActivityBinding
    var positionObservable = ObservableInt()

    companion object {
        private val TAG = QRBluetoothSwipeActivity::class.java.name
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)  

         // databinding init
        val binding = DataBindingUtil.setContentView<QrBluetoothSwipeActivityBinding>(
            this, R.layout.qr_bluetooth_swipe_activity
        )
        binding.setHandler(this)

        // viewbinding init
        viewBinding = QrBluetoothSwipeActivityBinding.inflate(layoutInflater)
        setContentView(viewBinding.root)

        init()
    }

 private fun init() {
        val customFragmentStateAdapter = CustomFragmentStateAdapter(this)
        customFragmentStateAdapter.addFragment(QrPageFragment())
        customFragmentStateAdapter.addFragment(BluetoothPageFragment())
        viewBinding.viewPager2.adapter = customFragmentStateAdapter

        viewBinding.viewPager2.registerOnPageChangeCallback(object :
            ViewPager2.OnPageChangeCallback() {
            override fun onPageSelected(position: Int) {
                if (BuildConfig.DEBUG) {
                    Log.d(TAG, "registerOnPageChangeCallback: position = $position")
                }
                positionObservable.set(position)
            }
        })
    }

my qr_bluetooth_swipe_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <import type="android.view.View" />

        <variable
            name="handler"
            type="com.myproject.actviity.QRBluetoothSwipeActivity" />

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.viewpager2.widget.ViewPager2
            android:id="@+id/viewPager2"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toTopOf="@+id/bottonContainer"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/bottonContainer"
            android:layout_width="0dp"
            android:layout_height="104dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent">

            <androidx.constraintlayout.widget.ConstraintLayout
                android:id="@+id/qrBottonMainContainer"
                android:layout_width="0dp"
                android:layout_height="104dp"
                android:visibility="@{handler.positionObservable == 0 ? View.GONE: View.VISIBLE}"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"/>

After start app then success swipe viewpager2. And as result success show the next message:

10-25 14:25:24.991 D/com.myproject.actviity.QRBluetoothSwipeActivity(23012): registerOnPageChangeCallback: position = 0

nice. But qrBottonMainContainer not hide. Why?

P.S. If I remove this:

viewBinding = QrBluetoothSwipeActivityBinding.inflate(layoutInflater)
setContentView(viewBinding.root)

then success work.

why?


Solution

  • You can't use them togheter in the same layout.

    ViewBinding is a subset of what DataBinding can do and should be used if you want to replace libraries like ButterKnife, KotterKnife or KAE (Kotlin Android Extensions) but don't want to invest in databinding refactoring.

    If you use DataBinding you already have the id reference of the views composing the layout in your binding object. Something like binding.myTextView.

    Remember that:

    • The data binding library only processes data binding layouts created using the <layout> tag.
    • View binding doesn't support layout variables or layout expressions, so it can't be used to bind layouts with data in XML.

    As per the documentation here

    PS: In your specific case you can't use <layout> tags with ViewBinding