Tìm hiểu Data Binding Library - Part 1
Bài đăng này đã không được cập nhật trong 3 năm
Xin chào các bạn, hôm nay tôi xin giới thiệu 1 library mới của android.
Khi lập trình Android có những lúc bạn mong ước rằng có cách nào đó có thể code Java ngay trên layout để có thể giảm tối thiểu các dòng code không cần thiết. Đặc biệt khi bạn cần hiển thị hàng trăm trường thông tin trên giao diện và bạn chán ngấy khi cứ phải findViewById()
rồi mới có thể gán giá trị cho chúng.
Data Binding Library là 1 thư viện hỗ trợ đắc lực cho vấn đề trên. Đây là 1 support library nên có thể sử dụng từ Andorid 2.1 (API 7+) trở lên.
Tôi xin cung cấp thêm là Library này hiện khá là mới với bản release đầu tiên vào ngày 28/5/2015 và phiên bản gần đây nhất 9/10/2015 vậy nên bạn cần phải thường xuyên cập nhật các version mới nhất để tránh các bug không đáng có.
Cấu hình môi trường
Để có thể bắt đầu sử dụng với Data Binding bạn hãy tải library Support repository trong Android SDK manager. Data Binding yêu cầu plugin Gradle từ bản 1.3.0-beta4 trở lên và phiên bản Android Studio từ 1.3 trở lên.
Hiện tại đã có phiên bản gradle 1.3.1 và databinding 1.0-rc4 nên trong bài viết này tôi sẽ sử dụng 2 phiên bản này
Tham khảo thêm các version dưới đây:
- Gradle : http://developer.android.com/tools/revisions/gradle-plugin.html
- DataBinding : https://bintray.com/android/android-tools/com.android.databinding.dataBinder/view
Cấu hình project Thêm đoạn code dưới đây vào build.gradle
dependencies {
classpath "com.android.tools.build:gradle:1.3.1"
classpath "com.android.databinding:dataBinder:1.0-rc4"
}
và trong repositories
allprojects {
repositories {
jcenter()
}
}
Trong mỗi module bạn muốn dùng data binding hãy thêm đoạn code sau
apply plugin: 'com.android.application'
apply plugin: 'com.android.databinding'
**Khai báo Data Binding **
Data-binding layout có cấu trúc như sau:
<layout>
<data>
.......
</data>
<ViewRoot>
<View />
......
</ViewRoot>
</layout>
Trong đó:
Thẻ <layout> là thẻ gốc dưới đó thẻ data và View Root Ví dụ:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
>
<data>
<variable
name="user"
type="com.nghiatt.demobinding.model.User"
/>
</data>
<LinearLayout
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<TextView
android:text="@{user.name}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
</layout>
Biến user trong data mô tả các thuộc tính hay đối tượng bạn sẽ sử dụng trong layout
<variable
name="user"
type="com.nghiatt.demobinding.model.User"
/>
Cú pháp để sử dụng trong attribute properties là " @{}
". Ví dụ:
<TextView
android:text="@{user.name}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
Data Object
Khai báo Object
Cách 1
public class User {
public String name;
public boolean isHappy;
public User(String name, boolean isHappy) {
this.name = name;
this.isHappy = isHappy;
}
}
Cách 2
public class User {
private String name;
private boolean isHappy;
public User(String name) {
this.name = name;
this.isHappy = true;
}
public User(String name, boolean isHappy) {
this.name = name;
this.isHappy = isHappy;
}
public boolean isHappy() {
return isHappy;
}
public void setIsHappy(boolean isHappy) {
this.isHappy = isHappy;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Sử dụng Data Binding thì 2 cách trên là như nhau. Với expression ở đây @{user.name}
được dùng trong đoạn xml dưới đây thì sẽ truy cập vào trường name
trong cách 1 và gọi method getName()
trong cách 2
<TextView
android:text="@{user.name}"
......
/>
Binding Data
Theo mặc định, Binding class sẽ được tạo ra dựa theo tên file layout. Tên file layout sẽ được chuyển thành Pascal case và thêm hậu tố "Binding".
Ví dụ:
Tên file layout là main_activity.xml
sẽ tạo ra class MainActivityBinding
. Tương tự activity_main.xml
-> ActivityMainBinding
Class Binding này sẽ quản lý các liên kết từ các thuộc tính layout (Ví dụ: biến user) với các thành phần View của layout và biết cách để gán giá trị cho các binding expression (ví dụ: @{user.name}
). Khai báo như sau:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
user = new User("User test text");
binding.setUser(user);
}
Vậy là xong. Giờ bạn có thể chạy thử để xem kết quả thế nào
Ngoài cách trên bạn có thể get Views bằng cách:
MainActivityBinding binding = MainActivityBinding.inflate(getLayoutInflater());
Nếu như bạn sử dụng Data Binding Items trong ListView hay RecyclerView Adapter thì bạn sử dụng:
ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
//or
ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);
Binding Events
Một cách đơn giản là bạn có thể sử dung attr android:onClick
để chỉ định cho 1 method trong Activity
Bạn có thể xem ví dụ dưới đây để hiểu rõ hơn:
Nếu bạn có 1 object và 2 method
public class MainBindingActivity{
public void onClickHappy(View view) {
...
}
public void onClickUnHappy(View view) {
...
}
}
Biểu thức để chỉ định Event cho View:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
>
<data>
<variable
name="user"
type="com.nghiatt.demobinding.model.User"
/>
<variable
name="handlers"
type="com.nghiatt.demobinding.MainBindingActivity"
/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.name}"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{user.isHappy ? handlers.onClickHappy : handlers.onClickUnHappy}"
android:text="Click"
/>
</LinearLayout>
</layout>
Và dưới đây là khởi tạo:
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setHandlers(this);
Layout Details
Imports
Có thể khai báo nhiều thẻ import
trong thẻ data
. Nó cho phép tham chiếu đến Classes trong layout giống như JAVA
<data >
<import type="android.view.View"/>
</data>
Và đây là biểu thức sử dụng:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitCenter"
android:src="@drawable/happy_face"
android:visibility="@{user.isHappy ? View.VISIBLE : View.GONE}"
/>
Khi xảy ra trường hợp conflicts, 1 trong số đó sửa tên thành “alias:
”:
<import type="android.view.View"/>
<import type="com.example.real.estate.View"
alias="Vista"/>
Giờ Vista
sẽ tham chiếu đến com.example.real.estate.View
và View
sẽ tham chiếu đến android.view.View
trong file layout
Hoặc thẻ import
để tham chiếu đến static field và static method trong biểu thức
<data>
<import type="com.example.MyStringUtils"/>
<variable name="user" type="com.example.User"/>
</data>
…
<TextView
android:text="@{MyStringUtils.capitalize(user.lastName)}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
Variables
Mỗi 1 thẻ variable
sẽ mô tả thuộc tính cho biến đó để có thẻ gán giá trị vào biểu thức.
<data>
<import type="android.graphics.drawable.Drawable"/>
<variable name="user" type="com.example.User"/>
<variable name="image" type="Drawable"/>
<variable name="note" type="String"/>
</data>
Các class Binding được tạo ra sẽ có method setter
và getter
cho mỗi biến. Các biến sẽ được khởi tạo giá trị mặc định của Java bằng cách gọi thông qua setter
Khi có các file layout cho nhiều cấu hình (Ví dụ landscape hoặc portrait) thì các biến sẽ được kết hợp lại với nhau và không được phép conflict giữa các biến
Custom Binding Class Names
Theo mặc định, Binding class sẽ được tạo ra dựa theo tên file layout. Tên file layout sẽ được chuyển thành Pascal case và thêm hậu tố "Binding". Lớp được sinh ra này sẽ được đặt dưới package của module
Nếu module nằm trong com.nghiatt.demobinding
thì class Binding sẽ được đặt trong com.nghiatt.demobinding.databinding
Binding class có thể đổi tên hay đặt trong gói khác bằng cách chỉ định trong class
attribute trong thẻ data
Ví dụ:
<data class="MainBinding">
...
</data>
Class MainBinding
sẽ được đặt trong package .databinding
trong package module
Ví dụ:
Package module là com.nghiatt.demobinding
thì MainBinding
sẽ được đặt trong com.nghiatt.demobinding.databinding.MainBinding
Nếu muốn đặt cùng với package module thì thêm tiền tố dấu ".
"
<data class=".MainBinding">
...
</data>
Thì lúc này sẽ là com.nghiatt.demobinding.MainBinding
Còn trong trường hợp muốn chỉ định rõ nằm trong package nào thì code như sau:
<data class="com.example.MainBinding">
...
</data>
Để hiểu rõ hơn về bài biết bạn có thể xem example dưới đây:
Xem source code tại đây GitHub
Tiếp theo
Trong phần tiếp theo tôi sẽ đi sâu hơn về Data Binding Libray và sẽ có ví dụ kết hợp với ListView, GridView, RecyclerView, ... thể hiện được sức mạnh của library mới này.
Tài liệu tham khảo
All rights reserved