Android中的MVP笔记之二: Data Binding 库的使用之layout绑定数据与事件。

上一篇介绍了mvp的实现思路,这里介绍android原生自带的数据绑定框架的使用。对于的官方工程也是放在mvp简介的介绍页面里的,

对应的官方Data Binding示例地址为:https://github.com/googlesamples/android-architecture/tree/todo-databinding/

也可以查看官方关于Data Binding 库的说明:http://developer.android.com/tools/data-binding/guide.html#data_objects

安卓的实现一个界面,正常的做法是新建一个Activity类,新建一个layout文件,在Activity的setContentView(R.layout.xxxxx);把Activity类与layout布局绑定,然后使用findViewById(R.id.xxxx)找到指定控件,然后对控件做相应的操作,对于列表控件显示也是大概相同的流程,都是View view = LayoutInflater.from(Context()).inflate(R.layout.xxx, viewGroup, false);找到父容器控件后再View.findViewById(R.id.xxx)找到具体的控件,对其进行相应的设置。

 

Data Binding 库能实现的功能是在layout布局文件定义时,就指定了数据与控件的绑定和界面事件的处理。省去了必须findViewById的麻烦,以及更好的做到数据与界面的分离。

1.控件与数据的绑定,在layout里指定控件的一些属性怎样与指定的数据绑定

android:text="@{task.title}"

代替以往的。((EditText)findViewById(R.id.add_task_title)).setText(task.getTitle());

<EditText
    android:id="@+id/add_task_title"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="@string/title_hint"
 android:text="@{task.title}"
    android:singleLine="true"
    android:textAppearance="@style/TextAppearance.AppCompat.Title" />

 

 

android:visibility="@{stats.showStatus ? View.VISIBLE : View.GONE}"

代替以往的findViewById(R.id.add_task_title).setVisibility(task.showStatus?View.VISIBLE: View.GONE);

<TextView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:text="@{stats.status}"
    android:textAppearance="?android:attr/textAppearanceMedium"
 android:visibility="@{stats.showStatus ? View.VISIBLE : View.GONE}" />

 

 

android:background="@{task.isCompleted?@drawable/list_completed_touch_feedback: @drawable/touch_feedback}"

代替以往的 View.setBackgroundResource(task.isCompleted?R.drawable.xxx: R.drawable/xx);

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:background="@{task.isCompleted ? @drawable/list_completed_touch_feedback : @drawable/touch_feedback}"
    android:orientation="horizontal"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingBottom="@dimen/list_item_padding"
    android:paddingTop="@dimen/list_item_padding"
    android:onClick="@{() -> actionHandler.taskClicked(task)}">

 

2.控件与方法的绑定,在layout里指定控件的一些点击接口或其他回调接口怎样与对应的方法绑定。

 android:onClick="@{() -> actionHandler.taskClicked(task)}"

代替View.setOnClickListener(new View.OnClickListener() {

    @Override    

    public void onClick(View v) {

    }

});

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:background="@{task.isCompleted ? @drawable/list_completed_touch_feedback : @drawable/touch_feedback}"
    android:orientation="horizontal"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingBottom="@dimen/list_item_padding"
    android:paddingTop="@dimen/list_item_padding"
 android:onClick="@{() -> actionHandler.taskClicked(task)}">

 

如何使用Data Binding 库

1.开发环境:

compileSdkVersion 25

buildToolsVersion "25.0.2"

classpath 'com.android.tools.build:gradle:2.3.0'

并不需要根项目声明apt插件,

classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'

也不需要在模块里

apply plugin: 'com.neenbedankt.android-apt'

只需要在用到的模块下加入下面语句。

dataBinding {
    enabled = true
}

 

2.1用于与界面绑定数据的java

    新建Java类,并继承 android.databinding.BaseObservable,把需要在layout布局里引用的方法,加上@Bindable注解或@BindingAdapter,  使用@Bindable注解过的方法可以直接使用在xml布局里,如下面定义的getName()方法,可以在layout里这样使用

android:text='@{"name:"+company.getName()}'
 

public class Company extends BaseObservable{
    ......省略若干代码
    @BindingAdapter({"bind:imageUrl", "bind:error"})
    public static void setIcon(ImageView view, String url, Drawable error) {
        Glide.with(view.getContext()).load(url).error(error).into(view);
    }

    @Bindable
    public String getName() {
        return name;
    }
    ......省略若干代码
}

如果layout里需要用到一些工具类里的静态方法,不需要继承BaseObservable,也不需要在方法前增加注解。

public class DateUtil{
    ......省略若干代码
    public static String getTime(long time) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        return sdf.format(time);
    }
    ......省略若干代码
}

 

2.2 用于与控件绑定事件的类,不需要使用注解。像普通的java类一样定义即可。

public class ActionHandler {
    private Context mContext;

    public ActionHandler(Context context) {
        this.mContext = context;
    }

    public void showTextDialog(String text) {
        new AlertDialog.Builder(mContext).setTitle("detail")
                .setMessage(text).create().show();
    }
}

在layout里即可调用:android:onClick="@{(tv)->actionHandler.showTextDialog(company.toString())}"

 

3.定义layout布局

不使用Data Binding 库的layout布局如下。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.databindtest.MainActivity">
    ......省略若干代码
</LinearLayout>

使用Data Binding库需要以layout为根标签,并加入一个data子标签

data标签里常用到的有variableimport标签,

variable标签引入的是一个需要在java代码里动态设置的对象,type字段是Java类的导入,相当于代码里的import android.databinding.BaseObservable;

name字段相当于变量名称。

当data标签里有如下的一段代码时,

<variable name="company" type="com.example.databindtest.Company" />

当自动生成的Data Binding对象会生成一个setCompany(com.example.databindtest.Company c)的方法

import  标签一般是声明需要引用一些工具类里的里的静态方法。

和一些用到的类型,如果app:error="@{@drawable/ic_launcher'}"  就需要先声明Drawable。

无论是绑定数据还是事件方法,都是找到对象然后调用相应的get方法或事件方法。

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
            name="company"
            type="com.example.databindtest.Company" />
        <variable
            name="actionHandler"
            type="com.example.databindtest.ActionHandler" />

        <import type="android.graphics.drawable.Drawable" />
        <import type="com.example.databindtest.DateUtil" />
    </data>


    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/company_item_root_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/cardview_dark_background"
        android:padding="8dp">

        <android.support.v7.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="8dp">

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">

                <android.support.v7.widget.CardView
                    android:id="@+id/cv_wrap"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="8dp">
                    <ImageView
                        android:id="@+id/iv_icon"
                        android:layout_width="80dp"
                        android:layout_height="80dp"
                        android:minHeight="80dp"
                        android:minWidth="80dp"
                        android:layout_centerVertical="true"
                        android:onClick="@{(tv) -> actionHandler.showImageDialog(company.getIcon())}"
                        app:error="@{@drawable/ic_launcher'}"
                        app:imageUrl="@{company.getIcon()}" />
                </android.support.v7.widget.CardView>

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="8dp"
                    android:layout_marginTop="8dp"
                    android:layout_toRightOf="@id/cv_wrap"
                    android:orientation="vertical">
                </LinearLayout>
            </RelativeLayout>
        </android.support.v7.widget.CardView>
    </FrameLayout>
</layout>

 

做完上面的工作后,已经准备好了数据实体对象和layout布局,如果这时候使用了android studio的Build->Make Module 'xxx'的编译某个模块的功能,如果没有编译出错,可以看到在相应的临时编译生成了对应的xxxBinding文件,如下图所示

 

只需要在Activity里简单的调用几句,就可以实现数据自动填充到View,并且绑定控件的事件处理方法。

  调用 Binding.setCompany(mCompany);会自动把数据填充到View上。

package com.example.databindtest;

import android.content.Context;
import android.databinding.DataBindingUtil;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;

import com.example.databindtest.databinding.CompanyItemLayoutBinding;

import java.util.List;

public class MainActivity extends AppCompatActivity {
    private Company mCompany;
    CompanyItemLayoutBinding mBinding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBinding = DataBindingUtil.bind(findViewById(R.id.company_item_root_layout));
        mCompany = Company.getCompanyList().get(0);
        mBinding.setActionHandler(new ActionHandler(this));
        mBinding.setCompany(mCompany);
        initView();
    }
    //......省略若干代码
    public void setting(View view) {
        mCompany.setIcon(((EditText)findViewById(R.id.et_company_icon_path)).getText().toString());
        mCompany.setName(((EditText)findViewById(R.id.et_company_name)).getText().toString());
        mCompany.setInfo(((EditText)findViewById(R.id.et_company_info)).getText().toString());
        mBinding.setCompany(mCompany);
    }
    //......省略若干代码
}
 

完整代码请查看

https://git.oschina.net/null_979_4294/MVP-DataBinding1

 

转载于:https://my.oschina.net/u/3038281/blog/849951

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值