Android DataBinding完全解析

前言

       2015年的Google IO大会上,Android 团队发布了一个数据绑定框架(Data Binding Library),官方原生支持 MVVM 模型。以后可以直接在 layout 布局 xml 文件中绑定数据了,无需再 findViewById然后手工设置数据了。其语法和使用方式和 JSP 中的 EL 表达式非常类似。


配置:

android {
    ....
    dataBinding {
        enabled = true
    }
}
首先我们肯定是先要和布局文件进行绑定

        ActivityLayoutDetailBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_layout_detail);

替换掉setContentView即可,ActivityLayoutDetailBinding这个类是自动生成的和你的布局文件名字一样,如果你想要去改变名字的话



    
    
接下来就是在布局文件里面引用代码中的对象

Part 1、先是声明类和对象

  
        
        
        
        

        
        
        
        
        

        

        

        

        
        
        

        

        
Part 2、引用对象中的方法和值

      1、简易的引用

        
       2、集合引用

        
        
这时我们在代码中调用binding的set方法便可以为其设置内容了

        List users = new ArrayList<>();
        User u = new User();
        u.setName("List User Name Data");
        users.add(u);
        binding.setList(users);

        Map map = new HashMap();
        map.put("one", "Map One Data");
        binding.setMap(map);
在引用的同时也可以加上简单的逻辑运算

       
        
        
        
        
        
        
        
等等,详情请看源码

然而上面引用的数值并不能随着用户的操作动态的改变,如果你想动态的改变需要使用Observable前缀的类,如:

        //使用绑定的集合
        /**
         * 如果要使用ObservableArrayMap类需要在layout里面导入 
         */
        user = new ObservableArrayMap<>();
        user.put(Fields.FIRST_NAME, "Google");
        user.put(Fields.LAST_NAME, "Inc.");
        user.put(Fields.AGE, 17);
        binding.setObserableMap(user);
对象的话需要继承BaseObservable并设置你索要观察的字段
public class DataUser extends BaseObservable {
    //继承BaseObservable类,想对谁进行监听则需要在get方法上面添加@Bindable注解,在set方法里面使用notifyPropertyChanged
    //注意到的是在这个方法里面要传入BR.name参数,这是Binding类为该字段生成唯一变量进行绑定
    private String name;
    private int age;
    private String info;
    @Bindable
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(BR.name);
    }

    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    public String getInfo() {
        return info;
    }
    public void setInfo(String info) {
        this.info = info;
    }
}

当你去执行小的工作的时候,想去节省时间或者减少配置可以使用ObservableField或者其兄弟

    //它们内部包含Observable对象,使用时要去创建public final类型的
    //为其赋值和取值操作:user.firstName.set("Google");  int age = user.age.get();
    public final ObservableField name = new ObservableField<>();
    public final ObservableInt age = new ObservableInt();
    public final ObservableField info = new ObservableField<>();

Part 3、添加事件处理方法

        
        
       
        
实现监听方法,保证参数个数、类型、返回值都要保证和你使用set时监听一样,不然就出报错。

    public void checkChanged(View view, boolean isCheck) {
        System.out.println("checkChanged:" + view + "    " + isCheck);
    }

    public boolean longClick(View view) {
        System.out.println("longClick:" + view);
        return true;
    }
Part 4、在布局中使用include

如果你需要用到从xml传过来的数据需要去使用bind:user属性,这里的user是你定义的实体类名

        
        

然后只需要在include布局里面声明之后便可以直接使用了。

Part 5、在布局中使用ViewStub

        /**
         * 为ViewStub设置监听,当显示的时候为它绑定数据,因为当不显示的ViewStub会在视图中消失
         */
        vs = (ViewStub) findViewById(R.id.viewstub);
        vs.setOnInflateListener(new ViewStub.OnInflateListener() {
            @Override
            public void onInflate(ViewStub stub, View inflated) {
                ViewstubBinding viewstubBinding = ViewstubBinding.bind(inflated);
                Info info = new Info();
                info.setInfo("Andly Info");
                viewstubBinding.setInfo(info);
                Drawable d = getResources().getDrawable(R.mipmap.ic_launcher);
                viewstubBinding.setDrawable(d);
            }
        });

    }

    public void toggleViewStub(View view) {
        vs.inflate();
    }

Part 6、在布局中使用RecycleView控件

          1、添加RecycleView控件

        
        
           2、为RecycleView定义适配器

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        ViewDataBinding viewDataBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), layoutId, parent, false);
        return new ViewHolder(viewDataBinding);
    }
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.binding.setVariable(variable, list.get(position));
        holder.binding.executePendingBindings();
        //当然这里你也可以为其设置点击如:
        //holder.binding.getRoot.setOnclickListener()
    }
    @Override
    public int getItemCount() {
        return list.size();
    }

    class ViewHolder extends RecyclerView.ViewHolder {
        ViewDataBinding binding;

        public ViewHolder(ViewDataBinding binding) {
            super(binding.getRoot());
            this.binding = binding;
        }
    }
               3、为RecycleView设置Adapter

        //这里注意的是一定要是BR.dataInfo不能是其它的常数
        MyAdapter adapter = new MyAdapter(list, R.layout.rv_item, BR.dataInfo);
        binding.setAdapter(adapter);
        binding.rv.setLayoutManager(new LinearLayoutManager(this));
这样就大功告成,然而在很多情况我们都需要去对每个Item进行处理,如显示网络图片等等,这里我们就需要使用数据绑定自定义属性的功能,看代码

        
    //当你在一个方法只需要一个参数的时候可以使用@BindingAdapter("imageUrlStr"),加上之后就可以在布局文件中直接使用imageUrlStr
    //运行之后就会调用loadImage方法
    @BindingAdapter("imageUrlStr")
    public static void loadImage(ImageView iv, String url) {
        Glide.with(iv.getContext()).load(url).into(iv);//这里使用Glide库
    }

    //上面是为loadImage传入一个参数,当传入两个或多个参数的时候应使用@BindingAdapter({"imagePath", "imageError"})
    //这个的ImageView自定义了两个属性一个是imagePath传入的是url,一个是imageError为Drawable
    @BindingAdapter({"imagePath", "imageError"})
    public static void downloadImage(ImageView iv, String url, Drawable error) {
        Glide.with(iv.getContext()).load(url).error(error).into(iv);
    }

Android DataBinding完全解析_第1张图片

上面的方法使用的是静态方法,如果你不想使用静态方法你需要重写一个数据绑定组件类去实现DataBindingComponent

public class MyComponent implements android.databinding.DataBindingComponent {
    private Utils utils;
    @Override
    public Utils getUtils() {
        if (utils == null) {
            utils = new Utils();
        }
        return utils;
    }
}
然后你需要在Activity为其进行设置

        //第一种方式
        DataBindingUtil.setDefaultComponent(new MyComponent());
        //第二种方式
        ActivityMyListViewBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_my_list_view,new MyComponent());
        //第三种方式
        DataBindingUtil.bind(root,new MyComponent());

最后有个不起眼的小功能,就是当使用数据绑定的时候在预览界面不能看到显示的内容,这时你可以为你的控件设置默认显示内容

android:text="@{placeName,default=PLACEHOLDER}"
Android DataBinding完全解析_第2张图片

注意:

不允许使用混合类型

        
        

源码下载:http://download.csdn.net/detail/weiwozhiyi/9644657

你可能感兴趣的:(Android开发)