W pierwszej części poświęconej bibliotece data binding poznaliśmy podstawy. Ten wpis zawiera część bardziej zaawansowanych zagadnień.
Jeszcze raz o podłączeniu danych
Oprócz przedstawionej koncepcji, którą przedstawiłem możemy także łaczyć dane z wyglądem w ten sposób:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</layout>Co ciekawe nie ma tutaj znaczników <Data>, ale za to jest znacznik <Layout> i on w zupełności wystarczy do wygenerowania klasy łączącej. W aktywności możemy uzupełnić dane w następujący sposób:
DatabindingActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.databinding_activity);
binding.textview.setText("Witaj na myenv.net ");Także możemy skorzystać setXxx() (patrz poprzedni artykuł), aby uzupełnić wszystkie dane za jednym zamachem 😉 W tym przypadku nie mamy dostepu do zmiennych w plikach XML więc bardziej złożone wyrażenia w @{} nie są dostępne. Istnieje jednak możliwość połączenia tych dwóch technik. Z poprzedniej części i przedstawionej powyżej.
Tag <include> w Layout
W układzie XML mamy takie coś:
<include
android:id="@+id/content_1"
layout="@layout/content_main" />
<include
android:id="@+id/content_2"
layout="@layout/content_main" />Jak do tego podpiąć się i wstawić wartości?
binding.content1.setNews(news2); binding.content2.setNews(News3);
Wzorzec dla dołączonych plików ma taki sam wzorzec jak w przypadku widoków. Czyli identyfikator znacznika <include> jest używany jako nazwa pola w klasie. Dołączony układ wygeneruje własną klasę z własnymi polami dla widoków w swoim układzie. Pamiętaj, aby nadać znacznikowi <include> identyfikator w przeciwnym wypadku pole nie zostanie mu nadane. Nic nie stoi na przeszkodzie abyśmy mogli wstawiać wszystkie wartości ręcznie:
binding.content.title.setText("Android Architecture Components: Data Binding");Zwróć uwagę na to, że zmieniają się nazwy pól. Jeśli nadałeś identyfikatorowi wartość „@+id/content_2” to nazwa pola będzie miała postać content2.
Wyrażenia
Opowiedziałem co nieco o wyrażeniach. Biblioteka umożliwia także wywołanie metod, skorzystanie z operatorów potrójnych i operacje matematyczne. Jak sprawdzić, czy dana wartość jest nullem?
android:text='@{ news.title ?? "Some title" }'Jest równoznaczne z:
android:text='@{news.title != null ? user.title : "Some title"}'Chcesz skorzystać z zasobów? Proszę bardzo:
android:padding='@{news.textpadding ? @dimen/textPaddingCompact : @dimen/textPaddingFull, default="10dp"}'Możesz również użyć formatowania łańcuchów zgodnie ze składnią metod getString, getQuantityString i getFraction. Po prostu przekazujesz parametry jako argumenty do zasobu.
android:text="@{String.format(@string/comment_format_string, news.comment)}"<string name="comment_format_string">Count comments: %s</string>
Wyświetli „Count comments: 10”. Zakładając, że news.comment nie będzie nullem 😉 Na chwilę obecną atrybut „style” jeszcze nie działa. W tym przypadku możesz skorzystać z BindingAdapter, który został opisany w poprzednim artykule.
Widoczność widoków
Pokazałem też w jaki sposób wyświetlić etykietkę premium w zależności od tego, czy wartość premium jest true. Sprawdźmy inny przykład w którym chcemy uzyskać dostęp do atrybutów widoku z poziomu wyrażeń.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="android.view.View" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<CheckBox
android:id="@+id/showSite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/site"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="@{showSite.checked ? View.VISIBLE : View.GONE}" />
</LinearLayout>
</layout>Powyższy przykład wyświetla nazwę strony w zależności od tego, czy checkbox jest zaznaczony, czy nie. Odwołujemy się do identyfikatorów w wyrażeniu. Nic trudnego.
Zależne właściwości
Co jeszcze można zmajstrować z @Bindable?, Załóżmy, że w naszej klasie News mamy taki kod:
@Bindable({ "title" , "site" })
public String getFulltitle () {
return title + " " + site;
}Adnotacja przyjmuje opcjonalne parametry do zadeklarowania zależności. Teraz metoda getFulltitle, a dokładnie zwraca jej wartośc jest zależna od właściwości title i site. To znaczy, Ilekroć zmieni się którakolwiek z tych wartości, wynik z metody również zostanie zaktualizowany.
Innym sposobem jest wysłanie powiadomienia za pomocą notifyPropertyChanged(BR.fulltitle). Adnotację tą dodajesz do każdego settera właściwości, który jest zależny. W naszym przypadku to title i site.
