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.