概述
Kotlin使用DataBinding+LiveData遇到的小坑
这两天在学习DataBinding的过程中遇到了一些问题,首先是网上的许多资料都还是gradle3.1之前的产物,对于先直已经默认整合DataBindingV1、V2版本,对kotlin的支持、尤其是在fragment中的使用没有很好的说明。
截止截稿,gradle版本已经到 3.5_rc1 了。
开启DataBinding,仍需要在项目的build.gradle中开启它
// An highlighted block
...
apply plugin: 'kotlin-kapt'
android{
...
//启用DataBinding
dataBinding {
enabled = true
}
//kotlin支持
kapt {
generateStubs = true
}
}
dependencies{
...
//lifecycle
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0-alpha02'
implementation 'androidx.lifecycle:lifecycle-runtime:2.2.0-alpha02'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0-alpha02'
kapt 'androidx.lifecycle:lifecycle-compiler:2.2.0-alpha02'
//databinding
kapt 'com.android.databinding:compiler:3.2.0-alpha10'
}
比如这里我新建了一个带viewModel的Fragment或Activity
WelcomeFragment.kt / WelcomeActivity.kt
WelcomeViewModel.kt
welcome_fragment.xml
ViewModel和其他代码就忽略不计了。
首先布局文件并非是在Activity或者Fragment自动生成的布局上直接添加data节点,而是需要添加一个新的layout文件,其节点为全小写的 <layout/> (当然也可以在原来的布局外面手动套一层layout)
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools ="http://schemas.android.com/tools">
...
<data>
<variable
name="viewModel"
type="com.android.test.WelcomeViewModel"/>
</data>
<!--这里开始就是原来实际上的根布局-->
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/cl_welcome"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
...
<TextView
android:id="@+id/tv_welcome_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{viewModel.msg}"
android:textColor="@color/textColorTip"
android:textSize="@dimen/TextSizeCommon"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintVertical_bias="0.75"
/>
</layout>
省略了大部分内容。
在TextView的text属性中对viewModel.msg进行了引用
于是就来到被坑了一段时间的LiveData绑定时间。
在Activity中
class WelcomeActivity: AppCompatActivity() {
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val mBinding= DataBindingUtil.setContentView<WelcomeFragmentBinding>(this,R.layout.welcome_fragment)
viewModel = ViewModelProviders.of(this).get(WelcomeViewModel::class.java)
mBinding.viewModel = viewModel
mBinding.lifecycleOwner = this
}
}
在Fragment中
class WelcomeFragment : Fragment() {
...
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val mBinding = DataBindingUtil.inflate<WelcomeFragmentBinding>(inflater, R.layout.welcome_fragment, container, false)
viewModel = ViewModelProviders.of(this).get(WelcomeViewModel::class.java)
mBinding.viewModel = viewModel
mBinding.lifecycleOwner = this
return mBinding.root
}
}
其实方法很简单,就是获取一个带DataBinding的View,然后绑定你在xml文件中设定的参数,最后把赋予DataBinding生命周期监听lifecycleOwner即可。只不过在Fragment中还需要通过root方法获取并返回View
坑就在于:
1、首先,大多数资料过老,都还是基于rxjava编写的。
2、起因的是谋篇博文,他的DataBinding实例mBinding没有指定类型,然后调用了一个mBinding.setViewModel()方法,我当时就愣住了,我翻遍ViewDataBinding类,哪有这个方法。这篇是java写的,还有一篇kotlin不知道是抄错了还是怎么回事,再一次误导了我,他直接就val了一个mBinding就开始给viewmodel赋值,返回的参数根本不带类型。
所以问题的关键在于,无论是Activity 的 setContentView方法还是Fragment的inflate方法,返回的都是继承于ViewDataBinding的参数。
而这个继承于ViewDataBinding的WelcomeFragmentBinding,是由带DataBinding的xml布局文件welcome_fragment.xml自动生成的,名字也是和布局文件的名字相关的,只要在xml文件中添加data之后进行sync,就会自动生成…
WelcomeFragmentBinding的lifecycleOwner、root方法都是继承自ViewDataBinding,但是上文代码中的viewModel指的却是你自己在xml中定义的变量
<data>
<variable
name="viewModel"
type="com.android.test.WelcomeViewModel"/>
</data>
总结:
总的来说这个事情还是因为我不够细心和耐心导致的,写下这篇笔记主要是出于记住教训的目的,同时也看看能不能帮到其他正在学习DataBinding的朋友少走些弯路。
最后
以上就是高贵鞋子为你收集整理的Kotlin使用DataBinding+LiveData遇到的小坑的全部内容,希望文章能够帮你解决Kotlin使用DataBinding+LiveData遇到的小坑所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复