数据绑定不能与 Kotlin 中的视图绑定一起使用
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"
在 app/build.gradle:
android {
viewBinding.enabled = true
dataBinding {
enabled = true
}
在我的 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)
}
})
}
我的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"/>
启动app后滑动成功viewpager2。
结果成功显示下一条消息:
10-25 14:25:24.991 D/com.myproject.actviity.QRBluetoothSwipeActivity(23012): registerOnPageChangeCallback: position = 0
不错。
但是qrBottonMainContainer
躲不开。为什么?
P.S。如果我删除这个:
viewBinding = QrBluetoothSwipeActivityBinding.inflate(layoutInflater)
setContentView(viewBinding.root)
然后成功工作。
为什么?
您不能在同一布局中同时使用它们。
ViewBinding
是 DataBinding
的一个子集,如果您想替换 ButterKnife
、KotterKnife
或 KAE(Kotlin Android 扩展)但不想投资于数据绑定重构。
如果您使用 DataBinding
,您已经在 binding
对象中拥有构成布局的视图的 ID 引用。类似于 binding.myTextView
.
记住:
- 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.
根据文档here
PS:在您的特定情况下,您不能将 <layout>
标签与 ViewBinding
一起使用
此处解决方案没有 viewbinding
android {
dataBinding {
enabled = true
}
在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.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
如果您想在单个布局中同时使用视图绑定和数据绑定
您只需要使用数据绑定,因为视图绑定是数据绑定的子集数据绑定提供视图绑定的功能。
两者的区别在于视图绑定仅用于视图引用而不用于与数据源绑定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"
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
}
在我的 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)
}
})
}
我的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"/>
启动app后滑动成功viewpager2。 结果成功显示下一条消息:
10-25 14:25:24.991 D/com.myproject.actviity.QRBluetoothSwipeActivity(23012): registerOnPageChangeCallback: position = 0
不错。
但是qrBottonMainContainer
躲不开。为什么?
P.S。如果我删除这个:
viewBinding = QrBluetoothSwipeActivityBinding.inflate(layoutInflater)
setContentView(viewBinding.root)
然后成功工作。
为什么?
您不能在同一布局中同时使用它们。
ViewBinding
是 DataBinding
的一个子集,如果您想替换 ButterKnife
、KotterKnife
或 KAE(Kotlin Android 扩展)但不想投资于数据绑定重构。
如果您使用 DataBinding
,您已经在 binding
对象中拥有构成布局的视图的 ID 引用。类似于 binding.myTextView
.
记住:
- 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.
根据文档here
PS:在您的特定情况下,您不能将 <layout>
标签与 ViewBinding
此处解决方案没有 viewbinding
android {
dataBinding {
enabled = true
}
在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.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
如果您想在单个布局中同时使用视图绑定和数据绑定 您只需要使用数据绑定,因为视图绑定是数据绑定的子集数据绑定提供视图绑定的功能。
两者的区别在于视图绑定仅用于视图引用而不用于与数据源绑定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"