美文网首页
2019-08-13 databinding 简单使用

2019-08-13 databinding 简单使用

作者: 猫KK | 来源:发表于2019-11-01 18:56 被阅读0次

    使用databinding首先得打开 databinding,在app目录下的build.gradle 中配置

    android {
        compileSdkVersion 29
        buildToolsVersion "29.0.1"
        defaultConfig {
            //......
        }
        //开启databinding
        dataBinding {
            enabled = true
        }
    }
    

    这样就可以使用databinding的功能,使用databinding需要生成一个xxxBinding,所以需要编写xml文件

    <?xml version="1.0" encoding="utf-8"?>
    <!--使用databinding ,最外层的节点必须是 layout-->
    <layout
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            tools:context="com.example.test.view.LoginActivity">
        <!--data 节点定义对应的数据,如下,我定义了LoginActivity 为view-->
        <!--定义了 LoginViewModel 为 viewmodel-->
        <!--定义之后在下面就可以使用-->
        <data>
            <variable name="view"
                      type="com.example.test.view.LoginActivity"/>
            <variable name="viewmodel"
                      type="com.example.test.viewmodel.LoginViewModel"/>
        </data>
        <androidx.constraintlayout.widget.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">
    
            <Button
                   android:text="@{viewmodel.text}"
                    android:onClick="@{() -> viewmodel.login()}"
                    android:id="@+id/bt_login"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    tools:ignore="MissingConstraints"/>
    
            <androidx.recyclerview.widget.RecyclerView
                    android:id="@+id/rv_login"
                    app:layout_constraintTop_toBottomOf="@+id/bt_login"
                    android:layout_width="match_parent"
                    app:activity="@{view}"
                    app:beans="@{viewmodel.mLoginBean}"
                    android:layout_height="wrap_content"/>
        </androidx.constraintlayout.widget.ConstraintLayout>
    </layout>
    

    上面<data>节点主要用于引入需要的类或者数据,上面我引入了 LoginActivity 和 LoginViewModel 这两个类,后面的设置再说。编写到这里,编译项目,就会生成 xxxBinding 类(xxx 是这个xml 的名称,比如我的xml 为 login_activiy.xml 对应生成的为 LoginActivityBinding),然后在对应的Activity 的onCreate 方法中绑定

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            //通过 DataBindingUtil 获取 ActivityLoginBinding 对象
            var  dataBinding = DataBindingUtil.setContentView<ActivityLoginBinding>(this, R.layout.activity_login)
            //将当前Activity 设置给 dataBinding.view 
            //注意 dataBinding.view  就是在编写xml 时候<data>节点下的view
            dataBinding.view = this
            //将 viewmodel 赋值
            dataBinding.viewmodel = LoginViewModel(application, LoginModel())
        }
    

    对于TextView和Button

    到这里,databinding 就设置完成。下面来介绍使用databinding来设置文本信息

        <Button
                    android:text="@{viewmodel.text}"
                    android:onClick="@{() -> viewmodel.login()}"
                    android:id="@+id/bt_login"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    tools:ignore="MissingConstraints"/>
    

    我们只需要在text中直接text ="@{xxx}"就可以设置button的文本信息,我这里使用viewmodel.text ,所以需要在LoginViewModel中定义text属性

        open class LoginViewModel(application: Application, model: LoginModel) : BaseViewModel<LoginModel>(application, model) {
    
        var mLoginBean: ObservableArrayList<BaseBean> = ObservableArrayList()
        //定义text,就可以直接在xml中使用
        var text: String = "login"
    }
    

    如果想动态修改text内容,则将text = "@={xxx.xxx}" @后增加一个等号,并且使用 ObservableField 来做数据双向绑定,这样修改数据时,就能相应的显示在界面上

        <Button
                    android:text="@={viewmodel.text}"
                    android:onClick="@{() -> viewmodel.login()}"
                    android:id="@+id/bt_login"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    tools:ignore="MissingConstraints"/>
    
    open class LoginViewModel(application: Application, model: LoginModel) : BaseViewModel<LoginModel>(application, model) {
    
        var mLoginBean: ObservableArrayList<BaseBean> = ObservableArrayList()
        var text = ObservableField<String>()
    
        init {
            text.set("login")
        }
    }
    

    关于设置点击事件,则在xml 中设置android:onClick="@{()->viewmodel.login()}" ,然后在 viewmodel 中创建login 方法

    open class LoginViewModel(application: Application, model: LoginModel) : BaseViewModel<LoginModel>(application, model) {
    
        var mLoginBean: ObservableArrayList<BaseBean> = ObservableArrayList()
        var text = ObservableField<String>()
    
        init {
            text.set("login")
        }
    
        fun login() {
            //点击事件,就会进来这里
        }
    }
    

    这样,点击事件就会进来的 login方法中,如果需要在点击事件中传递参数,则在xml中

        <Button
                    android:text="@={viewmodel.text}"
                    android:onClick="@{(it) -> viewmodel.login(it)}"
                    android:id="@+id/bt_login"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    tools:ignore="MissingConstraints"/>
    

    将 android:onClick="@{(it) -> viewmodel.login(it)}" ,这里的it可以任意填写,代表当前view本身,如果需要其他参数,在viewmodel.login(it,params.....)中添加即可,在LoginViewModel修改对应的方法:

    open class LoginViewModel(application: Application, model: LoginModel) :
            BaseViewModel<LoginModel>(application, model) {
    
            var mLoginBean: ObservableArrayList<BaseBean> = ObservableArrayList()
            var text = ObservableField<String>()
    
            init {
                text.set("login")
            }
    
            //添加了什么参数,就加上对应的参数即可
            fun login(view: View) {
                //点击事件,就会进来这里
            }
        }
    

    对于ImageView

    imagview 主要设置图片,在任意地方新建一个类:

    public class BindingImageLoad {
        @BindingAdapter({"app:image"})
        public static void setImage(ImageView image, String url) {
            Log.e("TAG", "---->" + url);
        }
    }
    

    使用@BindingAdapter 注解,配置需要的参数,在xml中使用

        <ImageView
                android:id="@+id/iv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:image="@{activity.image}"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/bt_click" />
    

    xml 中会出现@BindingAdapter注解中配置的参数,然后就会调用@BindingAdapter注解的方法,在这个方法里就可以用自己的方式来设置图片

    对于RecyclerView

    对于recycleview,和imageview一样,在任意地方创建类

    public class BindingAdapterInit {
    
        /**
         * 设置 LinearLayout 样式的 recyclerView
         *
         * @param recyclerView recyclerView 自身
         * @param beans        数据集
         * @param activity     当前activity
         */
        @BindingAdapter({"app:beans", "app:context"})
        public static void setLinearRecycler(RecyclerView recyclerView, List<BaseBean> beans, Context activity) {
            RecyclerView.Adapter adapter = recyclerView.getAdapter();
            if (adapter == null) {
                //创建adapter
            } else {
                adapter.notifyDataSetChanged();
            }
        }
    }
    

    和imagview一样,添加注解,最后会回调到这个方法中,在这里面可以设置RecyclerView的Adapter,关于RecyclerView 的item,如果也想使用,则需要修改一下Adapter

    public abstract class BaseBindingAdapter extends RecyclerView.Adapter<BaseBindingAdapter.MyHolder> {
    
        protected Context context;
    
        public BaseBindingAdapter(Context context) {
            this.context = context;
        }
    
        @NonNull
        @Override
        public BaseBindingAdapter.MyHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
           //获取Binding
           ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater.from(context), getLayoutId(), parent, false);
            return new MyHolder(binding.getRoot());
        }
    
        @Override
        public void onBindViewHolder(@NonNull BaseBindingAdapter.MyHolder holder, int position) {
             //注意需要调用executePendingBindings通知数据改变
            //没有调用可能数据改变了,视图没有改变
            ViewDataBinding binding = DataBindingUtil.getBinding(holder.itemView);
            setView(binding, holder, position);
            binding.executePendingBindings();
        }
    
        public abstract int getLayoutId();
    
        public abstract void setView(BaseBindingAdapter.MyHolder holder, int position);
    
        public class MyHolder extends RecyclerView.ViewHolder {
    
            public MyHolder(@NonNull View itemView) {
                super(itemView);
            }
        }
    }
    

    写一个类似这样的Adapte就可以在Item中也使用Binding了

    对于include

    如果需要使用include需要在include标签中添加bind:xxx,如下

    <include
                android:id="@+id/no_net"
                layout="@layout/fragment_home_not_net"
                android:visibility="gone"
                bind:viewmodel="@{viewmodel}" />
    
    <layout xmlns:app="http://schemas.android.com/apk/res-auto">
    
        <data>
    
            <variable
                name="viewmodel"
                type="com.dunya.muslims.viewmodel.HomeViewModel" />
        </data>
    
    ......
    </layout>
    

    在上面中,我需要传一个HomeViewModel过来,定义的名字为viewmodel,所以在include标签中添加bind:viewmodel,需要什么就bind:xxx 即可

    相关文章

      网友评论

          本文标题:2019-08-13 databinding 简单使用

          本文链接:https://www.haomeiwen.com/subject/pftbjctx.html