【问题标题】:Databinding not work together with viewbinding in Kotlin数据绑定不能与 Kotlin 中的视图绑定一起使用
【发布时间】:2020-02-21 18:07:03
【问题描述】:

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"

在 app/build.gradle 中:

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

在我的活动中:

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

我的 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"/>

启动应用后成功滑动viewpager2。 结果成功显示下一条消息:

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

很好。 但是qrBottonMainContainer 没有隐藏。为什么?

附:如果我删除它:

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

然后成功工作。

为什么?

【问题讨论】:

    标签: android kotlin android-databinding android-viewbinder


    【解决方案1】:

    您不能在同一布局中同时使用它们。

    ViewBindingDataBinding 可以做的一个子集重构。

    如果您使用DataBinding,则您已经在binding 对象中拥有组成布局的视图的ID 引用。类似binding.myTextView

    记住:

    • 数据绑定库仅处理使用&lt;layout&gt; 标签创建的数据绑定布局。
    • 视图绑定不支持布局变量或布局表达式,因此不能用于将布局与 XML 中的数据绑定。

    根据文档here

    PS:在您的具体情况下,您不能将&lt;layout&gt; 标签与ViewBinding 一起使用

    【讨论】:

    • 我添加了我的答案
    • 根据链接的文档,它们可以一起使用。 “在某些情况下,最好在项目中同时使用视图绑定和数据绑定”
    • @aaronmarino 文档只是说您应该根据布局需要/规范选择使用哪一个。但是您仍然不能在相同的布局上同时使用它们。限制是每个布局而不是每个项目
    • 嗯,好的。我将您的帖子误解为您不能在同一个项目中同时使用它们。
    【解决方案2】:

    这里没有viewbinding的解决方案

    android {
        dataBinding {
            enabled = true
        }
    

    活动中:

         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.ui.fragment.BluetoothPageFragment
            import com.myproject.ui.fragment.QrPageFragment
            import androidx.databinding.DataBindingUtil
            import androidx.databinding.ObservableInt
            import com.myproject.databinding.QrBluetoothSwipeActivityBinding
    
        class QRBluetoothSwipeActivity : AppCompatActivity() {
            private lateinit var dataBinding: QrBluetoothSwipeActivityBinding
            var positionObservable = ObservableInt()
    
            companion object {
                private val TAG = QRBluetoothSwipeActivity::class.java.name
            }
    
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                dataBinding = DataBindingUtil.setContentView<QrBluetoothSwipeActivityBinding>(
                    this, R.layout.qr_bluetooth_swipe_activity
                )
                dataBinding.setHandler(this)
                init()
            }
    
            private fun init() {
            val customFragmentStateAdapter = CustomFragmentStateAdapter(this)
            customFragmentStateAdapter.addFragment(QrPageFragment())
            customFragmentStateAdapter.addFragment(BluetoothPageFragment())
            dataBinding.viewPager2.adapter = customFragmentStateAdapter
    
            dataBinding.viewPager2.registerOnPageChangeCallback(object :
                ViewPager2.OnPageChangeCallback() {
                override fun onPageSelected(position: Int) {
                    if (BuildConfig.DEBUG) {
                        Log.d(TAG, "registerOnPageChangeCallback: position = $position")
                    }
                    positionObservable.set(position)
                }
            })
        }
    }
    

    现在它仅适用于数据绑定

    不错。

    感谢@MatPag

    【讨论】:

      【解决方案3】:

      如果您想在单个布局中同时使用视图绑定和数据绑定 您只需要使用数据绑定,因为视图绑定是数据绑定的子集,数据绑定提供视图绑定的功能。

      两者的区别在于视图绑定只针对视图引用,不用于绑定UI和数据源。

      android {
      buildFeatures {
          dataBinding true
        }
      }
      
      
      
      
         <layout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:app="http://schemas.android.com/apk/res-auto">
      <data>
          <variable
              name="viewmodel"
              type="com.myapp.data.ViewModel" />
      </data>
      
      </layout>
      
      
      
      
      val dataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
      dataBinding.executePendingBindings()
      dataBinding.tvName.text="View Binding"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-05-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-15
        • 2018-05-23
        • 1970-01-01
        相关资源
        最近更新 更多