Zobacz powiązanie Część systemu Android Jetpack.
Powiązanie widoku danych to funkcja ułatwiająca pisanie kodu, który wchodzi w interakcję z widokami danych. Gdy włączysz powiązanie widoku danych w module, wygeneruje ona klasę powiązania dla każdego pliku układu XML zawartego w tym module. Wystąpienie klasy powiązania zawiera bezpośrednie odwołania do wszystkich widoków, które mają identyfikator w odpowiednim układzie.
W większości przypadków wiązanie wyświetlenia zastępuje atrybut findViewById
.
Skonfiguruj
Powiązanie widoku jest włączone dla każdego modułu osobno. Aby włączyć powiązanie widoku w module, ustaw opcję kompilacji viewBinding
na true
w pliku build.gradle
na poziomie modułu, jak pokazano w tym przykładzie:
Odlotowy
android { ... buildFeatures { viewBinding true } }
Kotlin
android { ... buildFeatures { viewBinding = true } }
Jeśli chcesz, aby plik układu był ignorowany podczas generowania klas wiązania, dodaj atrybut tools:viewBindingIgnore="true"
do widoku głównego tego pliku układu:
<LinearLayout
...
tools:viewBindingIgnore="true" >
...
</LinearLayout>
Wykorzystanie
Jeśli w module jest włączone wiązanie widoku, dla każdego pliku układu XML zawartego w module jest generowana klasa powiązania. Każda klasa powiązania zawiera odwołania do widoku głównego i wszystkich widoków z identyfikatorem. Nazwa klasy powiązania jest generowana przez przekonwertowanie nazwy pliku XML na wielkość liter w formacie Pascal i dodanie na końcu słowa „Binding”.
Weźmy na przykład plik układu o nazwie result_profile.xml
, który zawiera:
<LinearLayout ... >
<TextView android:id="@+id/name" />
<ImageView android:cropToPadding="true" />
<Button android:id="@+id/button"
android:background="@drawable/rounded_button" />
</LinearLayout>
Wygenerowana klasa powiązania to ResultProfileBinding
. Ta klasa zawiera 2 pola: TextView
o nazwie name
i Button
o nazwie button
. Element ImageView
w układzie nie ma identyfikatora, więc nie ma do niego odwołania w klasie powiązania.
Każda klasa powiązania zawiera też metodę getRoot()
, która zapewnia bezpośrednie odwołanie do widoku głównego odpowiedniego pliku układu. W tym przykładzie metoda getRoot()
w klasie ResultProfileBinding
zwraca widok główny LinearLayout
.
W sekcjach poniżej pokazujemy, jak korzystać z wygenerowanych klas wiązań w aktywności i fragmentach.
Używanie powiązania widoku danych w działaniach
Aby skonfigurować instancję klasy powiązania na potrzeby działania, wykonaj te czynności w metodzie onCreate()
aktywności:
- Wywołaj statyczną metodę
inflate()
uwzględnioną w wygenerowanej klasie powiązania. Spowoduje to utworzenie instancji klasy powiązania, której ma używać działanie. - Możesz uzyskać odniesienie do widoku głównego, wywołując metodę
getRoot()
lub używając składni właściwości Kotlin. - Przekaż widok główny do
setContentView()
, aby ustawić go jako widok aktywny na ekranie.
Oto przykład:
Kotlin
private lateinit var binding: ResultProfileBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ResultProfileBinding.inflate(layoutInflater) val view = binding.root setContentView(view) }
Java
private ResultProfileBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ResultProfileBinding.inflate(getLayoutInflater()); View view = binding.getRoot(); setContentView(view); }
Możesz teraz użyć wystąpienia klasy powiązania, aby odwołać się do dowolnego z widoków:
Kotlin
binding.name.text = viewModel.name binding.button.setOnClickListener { viewModel.userClicked() }
Java
binding.name.setText(viewModel.getName()); binding.button.setOnClickListener(new View.OnClickListener() { viewModel.userClicked() });
Używanie powiązania widoku we fragmentach
Aby skonfigurować instancję klasy wiązania do użycia z fragmentem, wykonaj te czynności w metodzie onCreateView()
danego fragmentu:
- Wywołaj statyczną metodę
inflate()
uwzględnioną w wygenerowanej klasie powiązania. Spowoduje to utworzenie instancji klasy powiązania, której należy użyć dany fragment. - Możesz uzyskać odniesienie do widoku głównego, wywołując metodę
getRoot()
lub używając składni właściwości Kotlin. - Przywróć widok główny z metody
onCreateView()
, aby ustawić go jako widok aktywny na ekranie.
Kotlin
private var _binding: ResultProfileBinding? = null // This property is only valid between onCreateView and // onDestroyView. private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { _binding = ResultProfileBinding.inflate(inflater, container, false) val view = binding.root return view } override fun onDestroyView() { super.onDestroyView() _binding = null }
Java
private ResultProfileBinding binding; @Override public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { binding = ResultProfileBinding.inflate(inflater, container, false); View view = binding.getRoot(); return view; } @Override public void onDestroyView() { super.onDestroyView(); binding = null; }
Możesz teraz użyć wystąpienia klasy powiązania, aby odwołać się do dowolnego z widoków:
Kotlin
binding.name.text = viewModel.name binding.button.setOnClickListener { viewModel.userClicked() }
Java
binding.name.setText(viewModel.getName()); binding.button.setOnClickListener(new View.OnClickListener() { viewModel.userClicked() });
Podaj wskazówki dotyczące różnych konfiguracji.
Jeśli zadeklarujesz widoki danych w wielu konfiguracjach, czasami warto użyć innego typu widoku w zależności od konkretnego układu. Oto przykład takiego fragmentu kodu:
# in res/layout/example.xml
<TextView android:id="@+id/user_bio" />
# in res/layout-land/example.xml
<EditText android:id="@+id/user_bio" />
W tym przypadku wygenerowana klasa ujawni pole userBio
typu TextView
, ponieważ TextView
jest wspólną klasą bazową. Ze względu na ograniczenia techniczne generator kodów powiązania widoków nie może tego określić i zamiast tego generuje pole View
. Wymaga to późniejszego rzutowania pola za pomocą binding.userBio as TextView
.
Aby obejść to ograniczenie, powiązanie widoku obsługuje atrybut tools:viewBindingType
, co umożliwia kompilatorowi określenie typu do wykorzystania w wygenerowanym kodzie.
W poprzednim przykładzie możesz użyć tego atrybutu, aby kompilator wygenerował pole jako TextView
:
# in res/layout/example.xml (unchanged)
<TextView android:id="@+id/user_bio" />
# in res/layout-land/example.xml
<EditText android:id="@+id/user_bio" tools:viewBindingType="TextView" />
W innym przykładzie załóżmy, że masz 2 układy: jeden zawiera element BottomNavigationView
, a drugi NavigationRailView
. Obie klasy stanowią rozszerzenie NavigationBarView
, które zawiera większość szczegółów implementacji. Jeśli Twój kod nie musi wiedzieć, która podklasa występuje w bieżącym układzie, możesz użyć tools:viewBindingType
, aby ustawić wygenerowany typ na NavigationBarView
w obu układach:
# in res/layout/navigation_example.xml
<BottomNavigationView android:id="@+id/navigation" tools:viewBindingType="NavigationBarView" />
# in res/layout-w720/navigation_example.xml
<NavigationRailView android:id="@+id/navigation" tools:viewBindingType="NavigationBarView" />
Powiązanie widoku danych nie może zweryfikować wartości tego atrybutu podczas generowania kodu. Aby uniknąć błędów podczas kompilacji i czasu działania, wartość musi spełniać te warunki:
- Wartość musi być klasą dziedziczoną z
android.view.View
. Wartość musi być klasą nadrzędną tagu, w którym jest umieszczona. Na przykład nie działają te wartości:
<TextView tools:viewBindingType="ImageView" /> <!-- ImageView is not related to TextView. --> <TextView tools:viewBindingType="Button" /> <!-- Button is not a superclass of TextView. -->
Ostateczny typ musi występować spójnie we wszystkich konfiguracjach.
Różnice w stosunku do metody findViewById
Powiązanie widoku danych ma ważne zalety w porównaniu z używaniem findViewById
:
- Bezpieczeństwo zerowe: ponieważ powiązanie widoku danych tworzy bezpośrednie odwołania do widoków, nie ma ryzyka, że wyjątek wskaźnika o wartości null z powodu nieprawidłowego identyfikatora widoku danych.
Poza tym, gdy widok występuje tylko w niektórych konfiguracjach układu, pole zawierające jego odwołanie w klasie powiązania jest oznaczone dyrektywą
@Nullable
. - Bezpieczeństwo typu: typy pól w każdej klasie powiązania są zgodne z widokami danych, do których się odwołują w pliku XML. Nie ma więc ryzyka wyjątku rzutowania klasy.
Te różnice oznaczają niezgodności między układem a kodem, które powodują błędy kompilacji w czasie kompilacji, a nie w czasie działania.
Porównanie z wiązaniem danych
Zarówno widoki powiązań, jak i powiązania danych generują klasy powiązań, których można używać do bezpośredniego odwoływania się do widoków. Jednak wiązanie widoków służy do obsługi prostszych przypadków użycia i daje takie korzyści w porównaniu do wiązań danych:
- Szybsza kompilacja: wiązanie widoku nie wymaga przetwarzania adnotacji, co przyspiesza kompilację.
- Łatwość użycia: wiązanie widoku nie wymaga specjalnie otagowanych plików układu XML, dzięki czemu można szybciej zastosować je w aplikacjach. Po włączeniu wiązania widoku w module będzie ono automatycznie stosowane do wszystkich układów tego modułu.
Z drugiej strony wiązanie widoków ma następujące ograniczenia w porównaniu z powiązaniem danych:
- Powiązanie widoku danych nie obsługuje zmiennych układu ani wyrażeń układu, więc nie można go używać do deklarowania zawartości interfejsu dynamicznego bezpośrednio w plikach układu XML.
- Powiązanie widoku nie obsługuje dwukierunkowego wiązania danych.
Z tego powodu w niektórych przypadkach najlepiej jest używać w projekcie zarówno powiązań widoków, jak i danych. Możesz z nich korzystać w układach, które wymagają funkcji zaawansowanych, i w układach, które ich nie wymagają.
Dodatkowe materiały
Więcej informacji o powiązaniu widoku znajdziesz tutaj:
Próbki
Blogi
Filmy
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy JavaScript jest wyłączony
- Migracja z środowiska syntetycznego Kotlin do powiązania widoku Jetpack
- Układy i wyrażenia powiązania
- Architektura aplikacji: warstwa interfejsu – pierwsze kroki – deweloperzy aplikacji na Androida