Ngoài việc thay thế cho việc sử dụng findViewById hoặc ButterKnife datatabinding được xem như là một cách ứng dụng việc tách rời View và Logic.Trong bài này bằng cách ứng dụng Databinding chúng ta sẽ quản lý sự thay đổi những property của object và phản ánh nó lên view
Hướng dẫn bạn cách cài đặt
trong file app/gradle thêm vào như bên dưới
12345678 | build.gradleandroid{…dataBinding {enabled = true}} |
Bước 1: Trước tiên, thử hiển thị giá trị của object
Định nghĩa class sẽ bind
Chuẩn bị class User giống như bên dưới
1234567891011121314 | public class User{ private String name; public User(String name){ this.name = name;} public String getName() { return name;} public void setName(String name) { this.name = name;} |
Layout file
Ở tag root của filexml , định nghĩa object sẽ sử dụng bằng tag Ví dụ: định nghĩa một Object User với name là user(đặt tên tuỳ ý)Từ View để access một property của bind object chúng ta sử dụng @{}, viết như sau android:text=”@{user.name}”Nếu người dùng không định nghĩa getName() và field name là public thì sử dụng giá trị name như trên.Nhưng nếu gọi @{user.getName} mà không định nghĩa thì build thì bị lỗiNgoài ra, giá trị bên trong @{} được phép null, nghĩa là dù user null thì NullPointerException cũng không xãy ra.
1234567891011121314151617181920 | android:layout_width=”match_parent”android:layout_height=”match_parent”android:orientation=”vertical”> android:layout_width=”wrap_content”android:layout_height=”wrap_content”android:text=”@{user.name}” /> |
Bind một Object
Mặc định một Binding class có tên theo dạng PascalCase+Binding sẽ được tự động tạo ra dựa trên tên file xml layout tương ứng.Ví dụ:activity_main.xml => ActivityMainBindingfragment_sample.xml => FragmentSampleBindingTrong Activity, Fragment chúng ta có thể lấy được instance của các class Binding và liên kết mUser với user trong xml như bên dướiTrường hợp trong ActivityMainActivity.java
1234567891011 | private User mUser = new User(“Taro”); @Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); binding.setUser(mUser); //activity_main.xmlのuserにセットされる binding.setHandlers(this);} |
Trường hợp trong FragementSampleFragment.java
123456789 | private User mUser = new User(“Taro”); @Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { FragmentSampleBinding binding = DataBindingUtil.inflate(inflater, R.layout.fragment_sample, container, false); binding.setUser(mUser); //fragment_sample.xmlのuserにセットされる set return binding.getRoot();} |
Với code này sau khi build màn hình sẽ hiện text “Taro”
Bước 2: Nhận event phát sinh trên view
Ở Bước 2 và Bước 3 chúng ta sẽ thử thêm chức năng tự động thay đổi tên của user bằng button
Định nghĩa event
Ở phần trên chúng ta đã chỉ định của layout, ở phần này chúng ta sẽ đăng lý EventHandlerEventHandler. Chúng ta sẽ chuẩn bị một interface làm nhiệm vụ nhận event thay đổi tên của UserSampleEventHandlers.java
123 | public interface SampleEventHandlers { void onChangeClick(View view);} |
Để liên kế với click event thì parameter của onChangeClick phải giống với onClick() của View.OnClickListenerTương tự như User bằng cách khai báo trong tag , từ View có thể sử dụng được eventactivity_main.xml
1234 |
Liên kết event handler với click event
Để liên kết với event onclick của button chúng ta sẽ làm như sauandroid:onClick=”@{handlers.onChangeClick}”activity_main.xml
123456 | android:layout_width=”wrap_content” android:layout_height=”wrap_content” android:text=”CHANGE” android:onClick=”@{handlers.onChangeClick}” /> |
android:onClick của Button là thuộc tính tương ứng với onClick của View.OnClickListener và tên của thuộc tính cũng bắt nguồn từ tên method của listener.Ví dụ trường hợp của onLongClick của View.OnLongClickListener thì thuộc tính tương ứng sẽ là android:onLongClick
Implement event handler
Bây giờ chúng ta sẽ implement interface trong Activity và nhận event.MainActivity.java
123456789101112 | public class MainActivity extends AppCompatActivity implements SampleEventHandlers {private User mUser = new User(“Taro”); @Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); binding.setUser(mUser); binding.setHandlers(this);} |
Bây giờ chúng ta đã có thể đón event click của button và log sẽ được ghi.
Bước 3: Thay đổi động giá trị đang hiển thị
Tiếp theo khi button được click thử thay đổi tên User đang được hiển thịMainActivity.java
12345678 | @Overridepublic void onChangeClick(View view) { Log.d(“DEBUG”, “Change User Name”); mUser.setName(“Jiro”); Log.d(“DEBUG”, mUser.getName());} |
Nếu thử chạy code bên trên thì text “Jiro” sẽ hiển thị trong log nhưng trên màn hình vẫn giữ nguyên text “Taro”Để thông báo đến View những thay đổi của các property chúng ta phải thay đổi code một chút để có thể quản lý các Object
Trường hợp dùng cách kế thừa BaseObservable
User.java
123456789101112131415161718 | public class User extends BaseObservable{ private String name; public User(String name){ this.name = name; } @Bindable public String getName() { return name; } public void setName(String name) { this.name = name; notifyPropertyChanged(BR.name); }} |
Kế thừa lại class BaseObservable và thêm một chút thay đổi trong getter và setterTrước tiên gắn @Bindable trước getName(). Với cách này một hằng số BR.name sẽ được tạo ra.Tiếp theo, trong setName() thêm vào notifyPropertyChanged(BR.name). Lúc này từ layout, method getName()tương ứng với BR.name sẽ được gọi.Ở đây chúng ta đang gọi notifyPropertyChanged trong setter nhưng thật ra có thể gọi notifyPropertyChanged ở bất kỳ thời điểm nào bạn muốn thông báo sự thay đổi.
Trường hợp sử dụng ObservableField
Trường hợp nếu bạn không muốn dùng extends, có một cách khác là dùng ObservableField cho các field, khi đó chú ý là kiểu của các field sẽ là ObservableFieldUser.java
1234567 | public class User{ public ObservableField name = new ObservableField<>(); public User(String name){ this.name.set(name); }} |
Với thay đổi như trên, khi tap vào button tên của user sẽ tự động thay đổi.
Tổng kết
Ưu điểm của data binding là đối với phía sử dụng binding object thì chỉ cần set object chúng ta không cần quan tâm nó được sử dụng như thế nào nữa. Đối với event cũng vậy, chúng ta không cần phải quan tâm nó phát sinh từ view như thế nào.