iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 24
0
Software Development

Android Architecture系列 第 24

Data Binding Compiler V2

之前在Day4提過Google將會讓Data Binding也有lifecycle-aware效果,於是,新的Data Binding V2讓我們可以直接用LiveData來取代ObservableField,很方便地達成Data Binding的lifecycle-aware。

現在V2還在測試中,可在Android Studio 3.1 Canary 6以上的版本先行試用。

環境建置

要啟用V2版需先升級一下環境:

  1. 更改gradle版本至alpha06以上,目前最新是alpha07。
buildscript {
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.0-alpha07'
    }
}
  1. gradle-wrapper.properties中的distributionUrl最低須為gradle-4.4。
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
  1. gradle.properties中啟用V2。
android.databinding.enableV2=true

重新Build專案,如果Build完發現原本Data Binding的getRoot()等method不能用,可以用File -> Invalidate Cache/Restart重啟Android Studio就會正常了。

Data Binding V2

現在可以直接用LiveData取代ObservableField,假設要用Data Binding顯示讀取狀態的話,原寫法:

// ViewModel
public final ObservableField<Boolean> isLoading = new ObservableField<>();
isLoading.set(true);

// View
binding.setViewModel(viewModel);

新的寫法:

// ViewModel
public final MutableLiveData<Boolean> isLoading = new MutableLiveData<>();
isLoading.postValue(true);

// View
binding.setViewModel(viewModel);
binding.setLifecycleOwner(this);

用LiveData取代並加上setLifecycleOwner就讓Data Binding具有lifecycle-aware性質了。

那接著實際套用到我們的專案上,RepoViewModel中的LiveData repo在之前已經包裝過使其同時擁有資料及讀取狀態,只要把它改成public就可以用在Data Binding上。

public class RepoViewModel extends ViewModel {

    public final LiveData<Resource<List<Repo>>> repos;

   ...
}

在layout檔中設置<data>,並在ProgressBar用repos.status取得讀取狀態。

<?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"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <import type="android.view.View" />

        <import type="ivankuo.com.itbon2018.data.model.Status" />

        <variable
            name="viewModel"
            type="ivankuo.com.itbon2018.ui.RepoViewModel" />

    </data>

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        ...>
        
        ...

        <ProgressBar
            android:id="@+id/progressBar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:visibleGone="@{viewModel.repos.status == Status.LOADING}"
            ... />

    </android.support.constraint.ConstraintLayout>
</layout>

最後在RepoFragment中,綁定ViewModel和LifecycleOwner:

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    viewModel = ViewModelProviders.of(this, factory).get(RepoViewModel.class);
    binding.setViewModel(viewModel);
    binding.setLifecycleOwner(this);
    viewModel.getRepos().observe(...)
}

完成,之後ProgressBar就只會在View處於前景的時候才變更顯示狀態。


當初在#issue34看到yigit大神說將來會讓Data Binding具有lifecycle-aware性質時,還不曉得實際上會怎麼達成,結果是用個人覺得很好的做法:直接用LiveData取代,這樣除了有lifecycle-aware以外,也可以少寫幾個ObserverbleField在ViewModel中,讓程式更簡潔一致。

GitHub source code:
https://github.com/IvanBean/ITBon2018/tree/day24-data-binding-v2

Reference:
Architecture Components: How to use LiveData with Data Binding?


上一篇
Architecture Components - Paging
下一篇
RxJava2 - 簡介
系列文
Android Architecture30

尚未有邦友留言

立即登入留言