Wyświetl powiązanie Zawiera Android Jetpack.
Powiązanie widoków to funkcja, która ułatwia pisanie kodu interakcji, i widoki. Po włączeniu powiązania widoku w module generowane jest powiązanie class dla każdego pliku układu XML znajdującego się w tym module. Instancja powiązania klasa zawiera bezpośrednie odwołania do wszystkich widoków, które mają identyfikator w tagu odpowiadającego mu układu.
W większości przypadków powiązanie widoku zastępuje findViewById
.
Konfiguracja
Powiązanie widoku można włączyć dla każdego modułu osobno. Aby włączyć powiązanie widoków w
ustaw opcję kompilacji viewBinding
na true
na poziomie modułu
build.gradle
zgodnie z tym przykładem:
Odlotowe
android { ... buildFeatures { viewBinding true } }
Kotlin
android { ... buildFeatures { viewBinding = true } }
Jeśli chcesz, aby plik układu był ignorowany podczas generowania klas powiązań, dodaj
atrybut tools:viewBindingIgnore="true"
do widoku głównego danego układu,
plik:
<LinearLayout
...
tools:viewBindingIgnore="true" >
...
</LinearLayout>
Wykorzystanie
Jeśli w module włączone jest powiązanie widoku, dla każdego modułu generowana jest klasa powiązania pliku układu XML zawartego w module. Każda klasa powiązania zawiera odwołania do widoku głównego i wszystkich widoków, które mają taki identyfikator. Nazwa klasy powiązania to przez konwertowanie nazwy pliku XML na format Pascal i dodanie słowo „Wiązanie” do końca.
Weźmy np. plik układu o nazwie result_profile.xml
, który zawiera
następujące:
<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 nazywa się ResultProfileBinding
. Te zajęcia mają 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 odniesienia w
klasa powiązania.
Każda klasa powiązania zawiera również metodę getRoot()
, która zapewnia
odniesienia do widoku głównego odpowiedniego pliku układu. W tym przykładzie
metoda getRoot()
w klasie ResultProfileBinding
zwraca
LinearLayout
widok główny.
Sekcje poniżej pokazują użycie wygenerowanych klas powiązań w aktywności i fragmentów.
Używaj powiązania widoku w działaniach
Aby skonfigurować instancję klasy powiązania do użycia z działaniem, wykonaj
tych kroków w sekcji
Metoda onCreate()
:
- Wywołaj statyczną metodę
inflate()
uwzględnioną w wygenerowanej klasie powiązania. Spowoduje to utworzenie instancji klasy powiązania dla działania, które ma zostać użyte. - Uzyskaj odniesienie do widoku głównego, wywołując metodę
getRoot()
lub za pomocą właściwości Kotlin . - Przekaż widok główny do
setContentView()
aby stał się on aktywnym widokiem na ekranie.
Czynności te zostały pokazane w tym przykładzie:
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ć instancji 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żywaj wiązania widoku we fragmentach
Aby skonfigurować instancję klasy powiązania do użycia z fragmentem, wykonaj
kolejne kroki w tagu
onCreateView()
:
- Wywołaj statyczną metodę
inflate()
uwzględnioną w wygenerowanej klasie powiązania. Spowoduje to utworzenie instancji klasy powiązania, której ma użyć fragment. - Uzyskaj odniesienie do widoku głównego, wywołując metodę
getRoot()
lub za pomocą właściwości Kotlin . - Zwraca widok główny z metody
onCreateView()
, aby stał się Widok aktywny.
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ć instancji 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() });
Podawanie wskazówek dotyczących różnych konfiguracji
Deklarowanie wyświetleń w wielu konfiguracjach czasami powoduje, że używać różnych typów widoku w zależności od konkretnego układu. Oto przykładowy fragment 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 możesz oczekiwać, że wygenerowana klasa udostępni pole userBio
typu TextView
, ponieważ TextView
jest wspólną klasą bazową. Z powodu
ograniczenia techniczne, generator kodu wiązań widoków nie jest w stanie tego określić,
zamiast tego generuje pole View
. Wymaga to późniejszego przesyłania pola za pomocą
binding.userBio as TextView
Aby obejść to ograniczenie, powiązanie widoku obsługuje tools:viewBindingType
Dzięki temu możesz poinformować kompilatora, jakiego typu ma użyć w wygenerowanym kodzie.
W poprzednim przykładzie możesz użyć tego atrybutu, aby kompilator
wygeneruj 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 zawierający
BottomNavigationView
i drugi, który zawiera NavigationRailView
. Obie opcje
klasy rozszerzają zakres NavigationBarView
, który zawiera większość implementacji
. Jeśli Twój kod nie musi dokładnie wiedzieć, która podklasa znajduje się w
do bieżącego układu, możesz użyć tools:viewBindingType
, aby ustawić
wpisz 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 nie może zweryfikować wartości tego atrybutu podczas generowania kodu. Do uniknąć błędów podczas kompilacji i czasu działania, wartość musi spełniać następujące warunki:
- Wartość musi być klasą, która dziedziczy wartość z klasy
android.view.View
. Wartość musi być klasą nadrzędną tagu, na który jest umieszczona. Na przykład parametr następujące wartości nie działają:
<TextView tools:viewBindingType="ImageView" /> <!-- ImageView is not related to TextView. --> <TextView tools:viewBindingType="Button" /> <!-- Button is not a superclass of TextView. -->
Końcowy typ musi być spójnie rozpatrywany we wszystkich konfiguracjach.
Różnice w stosunku do parametru findViewById
Powiązanie widoków ma istotne zalety w porównaniu z korzystaniem z findViewById
:
- Bezpieczeństwo nudne: powiązanie widoków tworzy bezpośrednie odwołania do wyświetleń,
nie istnieje ryzyko wystąpienia wyjątku wskaźnika o wartości null z powodu nieprawidłowego identyfikatora widoku.
Poza tym, jeśli widok występuje tylko w niektórych konfiguracjach
układu, pole zawierające jego odwołanie w klasie powiązania jest oznaczone
dzięki
@Nullable
. - Bezpieczeństwo typu: pola we wszystkich klasach powiązania zawierają typy pasujące do wartości widoków, do których odwołują się w pliku XML. Oznacza to, że nie ma ryzyka związanego z zajęciami wyjątek przesyłania.
Te różnice oznaczają niezgodności między układem a kodem może prowadzić do awarii kompilacji w czasie kompilacji, a nie w czasie działania.
Porównanie z wiązaniem danych
Powiązanie widoków i powiązanie danych jest generowane klas powiązań, za pomocą których można odwoływać się bezpośrednio do widoków. Pamiętaj jednak wiązanie ma na celu obsługę prostszych przypadków użycia i zapewnia korzystny wpływ na wiązanie danych.
- Szybsza kompilacja: wiązanie widoku nie wymaga przetwarzania adnotacji, więc jest szybsze.
- Łatwość użycia: wiązanie widoków nie wymaga specjalnie otagowanego układu XML. Dzięki temu można szybciej wdrożyć je w aplikacjach. Po włączeniu powiązania widoku w moduł, zostanie on automatycznie zastosowany do wszystkich układów tego modułu.
Z drugiej strony wiązanie widoków wiąże się z tymi ograniczeniami w porównaniu z danymi. wiązanie:
- Powiązanie widoku nie obsługuje zmiennych lub układu układu wyrażeń, więc nie można go używać deklarowania dynamicznej treści UI bezpośrednio w plikach układu XML.
- Powiązanie widoku nie obsługuje danych dwukierunkowych
Z tego powodu w niektórych przypadkach najlepiej jest używać obu widoków i powiązania danych w projekcie. Wiązania danych możesz używać w układach, które: wymagają zaawansowanych funkcji i używają wiązania widoków w układach, które go nie używają.
Dodatkowe materiały
Więcej informacji o powiązaniu widoków znajdziesz w tych dodatkowych materiałach:
Próbki
Blogi
Filmy
.Polecane dla Ciebie
- Uwaga: tekst linku wyświetla się, gdy JavaScript jest wyłączony
- Migracja z syntetyki syntetycznej Kotlin do wiązania widoku Jetpack
- Układy i wyrażenia wiążące
- Architektura aplikacji: warstwa interfejsu – pierwsze kroki – deweloperzy aplikacji na Androida