ViewBinding vs Kotlin Rozszerzenia Androida z syntetycznymi widokami

38

Jak nowe ViewBinding ma się do rozszerzeń Kotlin dla Androida z syntetycznymi wiązaniami widoków?

Oprócz NullSafety i TypeSafety zapewnianych przez nowe ViewBindings, dlaczego warto rozważyć porzucenie Kotlinowskiego sposobu korzystania z syntetycznych powiązań w widokach.

Czy nowy ViewBinding jest bardziej wydajny, ponieważ wcześniej generuje klasę Binding?

Rinav
źródło
Stworzyłem nieco podobne pytanie na przedyskutuj.kotlinlang. Jeśli ktoś ma przemyślenia na ten temat, nie krępuj się odpowiedzieć :)
xinaiz
1
Spójrz na The Argument Over Kotlin Synthetics, aby uzyskać więcej informacji.
Cheticamp

Odpowiedzi:

69

Przyjrzyjmy się dwóm.


Konfiguracja

Rozszerzenia Kotlin dla Androida

  1. Zaimportuj odpowiednie rozszerzenia syntetyczne układu: import kotlinx.android.synthetic.main.<layout>.*
  2. Odnośnik widoki w kodzie poprzez ich identyfikatory: textView.text = "Hello, world!". Rozszerzenia te działają na: Activities, Fragmentsi Views.

Zobacz wiązanie

  1. Utwórz wiążące odwołanie w swojej klasie: private lateinit var binding YourClassBinding
  2. Nadmuchać swój wiążącej binding = YourClassBinding.inflate(layoutInflater)wnętrze Activity„y onCreatei połączenia setContentView(binding.root), czy napompować go w Fragment” s onCreateViewnastępnie powrócić go:return binding.root
  3. Odwołaj się do widoków w kodzie poprzez powiązanie przy użyciu ich identyfikatorów binding.textView.text = "Hello, world!"

Wpisz bezpieczeństwo

Rozszerzenia Kotlin dla systemu Android i ViewBinding są z definicji bezpieczne dla typów, ponieważ widoki odniesienia są już rzutowane na odpowiednie typy.


Brak bezpieczeństwa

Rozszerzenia Kotlin dla Androida i ViewBinding są bezpieczne. ViewBinding nie ma tu żadnej przewagi . W przypadku KAE , jeśli widok jest obecny tylko w niektórych konfiguracjach układu, IDE zwróci na to uwagę:

wprowadź opis zdjęcia tutaj

Więc traktujesz go jak każdy inny dopuszczający się do null typ w Kotlinie, a błąd zniknie:

wprowadź opis zdjęcia tutaj


Stosowanie zmian układu

W przypadku rozszerzeń Kotlin dla systemu Android zmiany układu natychmiast przekładają się na generowanie rozszerzeń syntetycznych, dzięki czemu można od razu z nich korzystać. W przypadku ViewBinding musisz zbudować swój projekt


Niepoprawne użycie układu

W przypadku rozszerzeń Kotlin dla systemu Android możliwe jest importowanie nieprawidłowych rozszerzeń układu, co powoduje NullPointerException. To samo dotyczy ViewBinding , ponieważ możemy zaimportować niewłaściwą Bindingklasę. Chociaż bardziej prawdopodobne jest przeoczenie niewłaściwego importu niż niepoprawnej nazwy klasy, szczególnie jeśli plik układu jest dobrze nazwany po Activity/ Fragment/ View, więc ViewBinding ma tutaj przewagę.


Podsumowanie KAE vs ViewBinding

  • Wpisz bezpieczeństwo - Rysuj.
  • Brak bezpieczeństwa - losowanie.
  • Kod bojlera - wygrywa KAE . Z dokumentacji rozszerzeń systemu Android Kotlin :

Wtyczka Kotlin Android Extensions pozwala nam uzyskać takie same wrażenia, jak w przypadku niektórych z tych bibliotek, bez konieczności dodawania dodatkowego kodu.

  • Stosowanie zmian układu - wygrywa KAE . Zmiany są natychmiastowe w przeciwieństwie do ViewBinding .
  • Niepoprawne użycie układu - wygrywa ViewBinding

Myślę, że istnieje duże nieporozumienie, że ViewBinding zastępuje KAE . Ludzie słyszą duże słowa kluczowe i powtarzają je bez uprzedniej weryfikacji. Jasne, ViewBinding jest obecnie najlepszą opcją do programowania Java (zamiennik ButterKnife ), ale nie ma żadnej lub ma niewielką przewagę nad KAE w Kotlin (patrz sekcja Nieprawidłowe użycie układu ).

Uwaga dodatkowa: Jestem pewien, że ludzie DataBinding polubią ViewBinding :)

Xinaiz
źródło
Dlaczego nic nie mówiłeś o używaniu zmiennych DataBinding? Myślę, że podstawową funkcją jest całkowite zaprzestanie korzystania z odniesień do widoku. Nawiasem mówiąc, możesz „rzucić” model widoku przez <include ... />tagi, co jest kolejną dużą zaletą.
Ircover
1
@Ircover Pytanie dotyczyło porównania KAE i ViewBinding. Wiązanie danych nie jest częścią tego pytania.
xinaiz
Ups, przepraszam) Proste nieporozumienie.
Ircover
1
@BenLewis, jeśli twoje wiązanie zdefiniowane jako lateinit nadal ma ten sam problem. Oznacza to, że bez licznika tego, czego używasz KAE lub ViewBinding, musisz przestrzegać pewnych ścisłych zasad podczas pisania kodu we fragmencie.
Flavio
1
„Stosowanie zmian układu” - Podczas korzystania z ViewBinding nie musisz budować projektu, po dodaniu nowego widoku z identyfikatorem możesz natychmiast wykonać „bind.myTextView ..”.
Tayyab Mazhar
19

ViewBindingrozwiązał największy problem kotlinx.android.synthetic. W syntheticwiążący, jeśli w Treści do układu, a następnie wpisz identyfikator, który istnieje tylko w innym układzie, IDE pozwala uzupełni i dodać nową instrukcję import. O ile programista nie sprawdzi, czy wyciągi importowe importują tylko prawidłowe widoki, nie ma bezpiecznego sposobu na sprawdzenie, czy nie spowoduje to problemów z czasem wykonywania. Ale w obiekcie ViewBindingpowinieneś użyć layoutobiektu wiązania, aby uzyskać dostęp do jego widoków, aby nigdy nie wywoływać widoku w innym układzie, a jeśli chcesz to zrobić, otrzymasz błąd kompilacji, a nie błąd wykonania. Oto przykład.

Tworzymy dwa układy zwane activity_maini activity_othertak:

Activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

    <TextView
        android:id="@+id/message_main"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

</RelativeLayout>

activity_other.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                >

    <TextView
        android:id="@+id/message_other"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

</RelativeLayout>

Teraz, jeśli napiszesz swoją aktywność w ten sposób:

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_other.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //Application will crash because "message_other" doesn't exist in "activity_main"
        message_other.text = "Hello!"
    }
}

kod zostanie skompilowany bez żadnego błędu, ale aplikacja ulegnie awarii w czasie wykonywania. Ponieważ widok o message_otheridentyfikatorze nie istnieje, activity_maina kompilator tego nie sprawdził. Ale jeśli używasz ViewBindingtak:

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        //This code will never compile and the IDE shows you an error
        binding.message_other.text = "Hello!"
    }
}

Twój kod nigdy się nie skompiluje i Android Studiowyświetli błąd w ostatniej linii.

Squti
źródło
1
Możesz także użyć LayoutInflater, aby napompować widok, a następnie odwołać się do zdefiniowanych pól za pomocą zmiennej.
NapoleonTheCake
4
Wydaje się to bardzo mało prawdopodobne w prawdziwym scenariuszu.
Bencri
1
Ten przykład nie ma sensu. Użyłeś go nieprawidłowo. Dlaczego miałbyś importować niepoprawną rzecz (activity_other)? Każda struktura, której używasz niepoprawnie, może powodować problemy.
programista Androida
2

kotlinx.android.synthetic nie jest już zalecaną praktyką, powiedział Google w jednym komunikacie zatwierdzenia „jednym z wątków Reddit

https://android-review.googlesource.com/c/platform/frameworks/support/+/882241 "

Synthetics nie jest rozwijany przez google, jest częścią rozszerzenia kotlin dla Androida stworzonego przez JetBrains i stopniowo google programiści Androida zaczęli zamieniać Synthetics na ViewBindins w swoich demach i kodach źródłowych.

„Teraz pojawia się pytanie, które musimy wziąć pod uwagę.”

Według google (View binding, ButterKnife, Kotlin syntetyki) biblioteki te są z powodzeniem używane przez wiele aplikacji i rozwiązują ten sam problem.

Jednak w przypadku większości aplikacji Google zaleca wypróbowanie powiązania widoku zamiast tych bibliotek, ponieważ wiązanie widoku zapewnia bezpieczniejsze, bardziej zwięzłe wyszukiwanie widoku.

Załączony obraz odniesienia, aby szybko wyczyścić. wprowadź opis zdjęcia tutaj

Jeśli jednak chcesz przejść do dept, możesz użyć poniższego linku. https://medium.com/androiddevelopers/use-view-binding-to-replace-findviewbyid-c83942471fc

SourabhTech
źródło
2
1. Zawsze bezpieczne - wiązanie View nadal będzie się zawieszać, jeśli zostanie użyte przed nadmuchaniem lub po zakończeniu cyklu życia widoku - nic innego niż syntetyki - powinno mieć CZERWONĄ wartość dla ViewBinding. 2. Odwołaj się tylko do identyfikatorów z bieżącego układu - to prawda, ale IDE wskazuje, z którego układu chcesz zaimportować dany identyfikator, więc nie jest to duży problem. 3. Obsługuje Kotlin i Javę - zły argument, jeśli możesz używać Kotlin w rozwoju Androida, to po co używać Java. 4. Wymagana ilość kodu - syntetyka Kotlin ma najniższą ilość, powinna być bardzo niska w tabeli.
xinaiz
@xinaiz Dlaczego używasz go przed napompowaniem, postępuj we właściwy sposób, aby użyć go w przeciwnym razie na pewno napotkasz problemy. Czy przeszedłeś przez link przed oddaniem opinii i opublikowaniem komentarza medium.com/androiddevelopers/…
SourabhTech
Tak, przeczytałem to jakiś czas temu. Nie używam go przed napompowaniem, po prostu mówię, że to możliwe. „Właściwy sposób” oznacza, że ​​istnieje ryzyko, prawda? Pominąłeś też or after view lifecycle endsczęść?
xinaiz
@xinaiz 2. Ale istnieje szansa na użycie niewłaściwego identyfikatora, jeśli projekt jest większy, a także dla tej samej nazwy zasobu, jeśli wielu programistów pracuje nad projektem. 3.Tak może istnieć wymóg dotyczący projektu, w którym musisz używać zarówno java, jak i kotlin (jeśli projekt jest już opracowany w java i rozpoczęto intruzję z kotlin, to zdecydowanie pomaga) 4. W przypadku Synthetics musisz zaimportować osobną bibliotekę, ale aby wyświetlić wiązanie jest już w Gradle, więc oczywiście zajęło mniej kodu.
SourabhTech
1
W odpowiedzi na 4. Jaką bibliotekę? Jest domyślnie włączony. To teza o apply plugin: 'kotlin-android-extensions'vs viewBinding { enabled = true }. Niewielka różnica.
xinaiz