Android中的MVP筆記之二: Data Binding 庫的使用之layout綁定數據與事件。

上一篇介紹了mvp的實現思路,這裏介紹android原生自帶的數據綁定框架的使用。對於的官方工程也是放在mvp簡介的介紹頁面裏的,html

對應的官方Data Binding示例地址爲:https://github.com/googlesamples/android-architecture/tree/todo-databinding/java

也能夠查看官方關於Data Binding 庫的說明:http://developer.android.com/tools/data-binding/guide.html#data_objectsandroid

安卓的實現一個界面,正常的作法是新建一個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)找到具體的控件,對其進行相應的設置。git

 

Data Binding 庫能實現的功能是在layout佈局文件定義時,就指定了數據與控件的綁定和界面事件的處理。省去了必須findViewById的麻煩,以及更好的作到數據與界面的分離。github

1.控件與數據的綁定,在layout裏指定控件的一些屬性怎樣與指定的數據綁定app

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

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

<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

相關文章
相關標籤/搜索