是时候更新手里的武器了—Jetpack架构组件简析( 二 )

然后绑定到布局中 , 这时候这个User的name属性就是被观察对象了 , 如果userName改变 , 布局里面的TextView显示数据也会跟着改变 , 这就是可观察数据对象 。
3)生成的绑定类
刚才我们获取绑定布局是通过DataBindingUtil.setContentView方法生成ActivityMainBinding对象并绑定布局 。那么ActivityMainBinding类是怎么生成的呢?只要你的布局用layout属性包围 , 编译后就会自动生成绑定类 , 类名称基于布局文件的名称 , 它会转换为 Pascal 大小写形式并在末尾添加 Binding 后缀 。
正常创建绑定对象是通过如下写法:
//Activityoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)val binding: MyLayoutBinding = MyLayoutBinding.inflate(layoutInflater)setContentView(binding.root)}//Fragment@Nullablefun onCreateView( inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {mDataBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_layout, container, false)return mDataBinding.getRoot()}4)绑定适配器
适配器这里指的是布局中的属性设置 , android:text="@{user.name}"表达式为例 , 库会查找接受user.getName()所返回类型的setText(arg) 方法 。重要的是 , 我们可以自定义这个适配器了 , 也就是布局里面的属性我们可以随便定义它的名字和作用 。来个
@BindingAdapter("imageUrl")fun loadImage(view: ImageView, url: String) {Picasso.get().load(url).into(view)}<ImageView App:imageUrl="@{venue.imageUrl}" />在类中定义一个外部可以访问的方法loadImage , 注释@BindingAdapter里面的属性为你需要定义的属性名称 , 这里设置的是imageUrl 。所以在布局中就可以使用app:imageUrl , 并传值为String类型 , 系统就会找到这个适配器方法并执行 。
5)将布局视图绑定到架构组件这一块就是实际应用了 , 和jetpack其他组件相结合使用 , 形成完整的MVVM分层架构 。
// Obtain the ViewModel component.val userModel: UserViewModel by viewModels()// Inflate view and obtain an instance of the binding class.val binding: ActivityDatabindingMvvmBinding =DataBindingUtil.setContentView(this, R.layout.activity_databinding_mvvm)// Assign the component to a property in the binding class.binding.viewmodel = userModel<data><variablename="viewmodel"type="com.panda.jetpackdemo.dataBinding.UserViewModel" /></data>class UserViewModel : ViewModel() {val currentName: MutableLiveData<String> by lazy {MutableLiveData<String>()}init {currentName.value=https://www.isolves.com/it/cxkf/jiagou/2020-08-02/"zzz"}}6)双向数据绑定
刚才我们介绍的都是单向绑定 , 也就是布局中view绑定了数据对象 , 那么如何让数据对象也对view产生绑定呢?也就是view改变的时候数据对象也能接收到讯息 , 形成双向绑定 。
很简单 , 比如一个EditText , 需求是EditText改变的时候 , user对象name数据也会跟着改变 , 只需要把之前的"@{}"改成"@={}"
//布局 activity_main.xml<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android"><data><variable name="user" type="com.example.User"/></data><EditText android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@={user.name}"/></layout>很简单吧 , 同样 , 这个双向绑定功能也是支持自定义的 。来个
object SwipeRefreshLayoutBinding {//方法1 , 数据绑定到view@JvmStatic@BindingAdapter("app:bind_refreshing")fun setSwipeRefreshLayoutRefreshing(swipeRefreshLayout: SwipeRefreshLayout,newValue: Boolean) {if (swipeRefreshLayout.isRefreshing != newValue)swipeRefreshLayout.isRefreshing = newValue}//方法1 , view改变会通知bind_refreshingChanged , 并且从该方法获取view的数据@JvmStatic@InverseBindingAdapter(attribute = "app:bind_refreshing",event = "app:bind_refreshingChanged")fun isSwipeRefreshLayoutRefreshing(swipeRefreshLayout: SwipeRefreshLayout): Boolean =swipeRefreshLayout.isRefreshing//方法3 , view如何改变来影响数据内容@JvmStatic@BindingAdapter("app:bind_refreshingChanged",requireAll = false)fun setOnRefreshListener(swipeRefreshLayout: SwipeRefreshLayout,bindingListener: InverseBindingListener?) {if (bindingListener != null)swipeRefreshLayout.setOnRefreshListener {bindingListener.onChange()}}}<androidx.swiperefreshlayout.widget.SwipeRefreshLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"app:bind_refreshing="@={viewModel.refreshing }"></androidx.swiperefreshlayout.widget.SwipeRefreshLayout>


推荐阅读