Tìm Hiểu Data Binding Library - Part 2
Bài đăng này đã không được cập nhật trong 3 năm
Trong phần trước các bạn đã hiểu được cách thức triển khai cơ bản cho databinding (https://viblo.asia/tran.thanh.nghia/posts/lA7GKnnoMKZQ)
Nhưng trước khi đi vào phần 2 này tôi xin cập nhật cách cấu hình môi trường mới được thay đổi trong Gradle (1.5.0-beta1 Chi tiết xem trong http://tools.android.com/tech-docs/new-build-system )
Và thêm đoạn code dưới đây
android {
....
dataBinding {
enabled = true
}
}
Và dưới đây
dependencies {
classpath 'com.android.tools.build:gradle:1.5.0-beta1'
}
Trong phần 2 này tôi sẽ trình bày các kiến thức còn lại về Data Binding và kết hợp với các UI Control khác
Expression Language
Sau khi đọc qua part 1 thì ắt hẳn bạn sẽ thắc mắc rằng liệu có thể thực hiện các phép tính cơ bản như +, -, *, / ,... trên xml được không ?. Tôi xin trả lời có vì expression language của Data Binding có khá nhiều điểm giống với Java expression.
- Toán học + - * /
- Nối chuỗi +
- Phép logic && ||
- Phép nhị phân & | ^
- Unary + - ! ~
- Phép dịch bit >> >>> <<
- Phép so sánh == != <= >=
instanceof
- Gom nhóm ()
- Cast
- Gọi method
- Truy cập field
- Truy cập mảng
- Toán tử ternary ?:
Ví dụ:
android:text="@{String.valueOf(index + 1)}"
android:visibility="@{age < ; 13 ? View.GONE : View.VISIBLE}"
android:transitionName='@{"image_" + id}'
< ;
tương đương với <
Các toán tử còn thiếu
1 vài toán tử bị thiếu trong expression syntax. Bạn có thể sử dụng toán tử này trong code Java
- this
- super
- new
- Triền khai generic
Toán tử Null Coalescing
là toán tử (??) sẽ chọn toán hạng bên trái nếu nó khác null. Chọn bên phải đi toán hạng bằng null
android:text="@{user.displayName ?? user.lastName}"
Nếu triển khai rõ ràng hơn thì như sau:
android:text="@{user.displayName != null ? user.displayName : user.lastName}"
Binding nâng cao
Biến động
Đội khi các data binding class không biết cách triển khai
Ví dụ RecyclerView.Adapter
thì cách triển khai như sau
public void onBindViewHolder(BindingHolder holder, int position) {
final T item = mItems.get(position);
holder.getBinding().setVariable(BR.item, item);
holder.getBinding().executePendingBindings();
}
Immediate Binding (thực thi tức thì)
Khi biến thay đổi giá trị thì các Binding sẽ lập lịch để thay đổi trong frame tiếp theo. Tuy nhiên để bắt thực hiện ngay thì ta dùng executePendingBindings()
để có thể update ngay data trên giao diện
Attribute Setters
Trong phần này tôi sẽ trình bày cách để custom attribute trong xml.
Automatic Setters
Đối với mỗi 1 attr thì Data Binding sẽ tìm method Setter của attribute đó. Phần namespace của attr không quan trọng, quan trọng là tên của attr
Ví dụ biểu thức binding được viết trong TextView's attribute android:text
thì sẽ tìm setText(String) tương ứng. Nếu biểu thức trả về int thì data binding sẽ tìm method setText(int)
Trong đó:
android là namespace
text là tên attribute
Renamed Setters
Sẽ có lúc tên attribute có setter không trùng tên với nhau. Với trường hợp này bạn cần chỉ định rõ attribute đó tương ứng với method setter nào
Ví dụ: có attr android:tint
có setter tương ứng là setImageTintList(ColorStateList)
nhưng nếu bạn không chỉ định rõ setter thì data binding sẽ tự động tìm tới setTint
(setTint - không tồn tại)
Lúc này bạn cần code như sau:
@BindingMethods({
@BindingMethod(type = "android.widget.ImageView",
attribute = "android:tint",
method = "setImageTintList"),
})
Custom Setters
Data Binding cung cấp custom attribute (BindingAdapter
) trong trường hợp bạn cần custom lại logic của attribute đó
Ví dụ ImageView
bạn cần load image từ 1 url nào đó trên mạng
@BindingAdapter({"bind:imageUrl", "bind:error"})
public static void loadImage(ImageView view, String url, Drawable error) {
Picasso.with(view.getContext()).load(url).error(error).into(view);
}
Data Binding cho phép nhận nhiều parameter
Khai báo trong xml:
<ImageView app:imageUrl=“@{venue.imageUrl}”
app:error=“@{@drawable/venueError}”/>
Như bạn đã thấy nó khá dễ dàng cho việc sử dụng các Library khác để implement vào trong project của bạn
Sử dụng Data Binding Library trong RecyclerView
Việc triển khai code khá đơn giản
Trong RecyclerViewAdapter
public static class BindingHolder extends RecyclerView.ViewHolder {
private ViewDataBinding binding;
public BindingHolder(View v) {
super(v);
binding = DataBindingUtil.bind(v);
}
public ViewDataBinding getBinding() {
return binding;
}
}
@Override
public void onBindViewHolder(BindingHolder holder, int position) {
final User user = mList.get(position);
holder.getBinding().setVariable(BR.user, user);
holder.getBinding().setVariable(BR.index,position+"");
holder.getBinding().executePendingBindings();
}
Khai báo trong item_recycler_view.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="index"
type="String"/>
<variable
name="user"
type="com.nghiatt.demobinding.model.User"
/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:text="@{index}"
/>
<TextView
android:text="@{user.name}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</layout>
Custom Attribute text của TextView app:text="@{index}
@BindingAdapter("text")
public static void setText(TextView textView, String text) {
textView.setText("custom attr item " + text);
}
Cuối bài tôi xin gửi demo cho việc kết hợp Data Binding với RecyclerView tại **đây GitHub ** (https://github.com/NghiaTran92/DemoDataBinding/tree/data_binding_part_2)
Kết luận
Cảm nhận mỗi người là khác nhau. Vậy nên tôi khuyên bạn hãy sắn tay áo lên và hãy bắt đầu code vài sample của mình về Data Binding Library. Lúc đó bạn sẽ cảm nhận được những điều tuyệt vời mà Data Binding mang lại
Tài liệu tham khảo
All rights reserved