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():

  1. 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.
  2. Uzyskaj odniesienie do widoku głównego, wywołując metodę getRoot() lub za pomocą właściwości Kotlin .
  3. 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() :

  1. 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.
  2. Uzyskaj odniesienie do widoku głównego, wywołując metodę getRoot() lub za pomocą właściwości Kotlin .
  3. 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:

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

. .