Nie można „znaleźćViewById” w Kotlinie. Pojawia się błąd „Wnioskowanie o typie nie powiodło się”

80

Gdy próbuję znaleźć RecycleViewidentyfikator według identyfikatora, pojawia się następujący błąd .

Błąd: - wnioskowanie o typie nie powiodło się: za mało informacji, aby wywnioskować parametr T

Błąd

Kod:

class FirstRecycleViewExample : AppCompatActivity() {
    val data = arrayListOf<String>()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.first_recycleview)

        val recycler_view =  findViewById(R.id.recycler_view) as RecyclerView ///IN THIS LINE I AM GETTING THE ERROR

        data.add("First Data")
        data.add("Second Data")
        data.add("Third Data")
        data.add("Forth Data")
        data.add("Fifth Data")

        //creating our adapter
        val adapter = CustomRecycleAdapter(data)

        //now adding the adapter to recyclerview
        recycler_view.adapter = adapter
    }
}
Ravindra Kushwaha
źródło

Odpowiedzi:

101

Spróbuj czegoś takiego:

val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)

Możesz Kotlin Android Extensionsteż do tego użyć . Sprawdź dokument tutaj .
Dzięki niemu możesz dzwonić recycler_viewbezpośrednio w swoim kodzie.

Rozszerzenia Kotlin na Androida:

  • W swojej aplikacji gradle.builddodajapply plugin: 'kotlin-android-extensions'
  • W swojej klasie dodaj import dla import kotlinx.android.synthetic.main.<layout>.*gdzie <layout>jest nazwa pliku twojego układu.
  • To wszystko, możesz zadzwonić recycler_viewbezpośrednio w swoim kodzie.

Jak to działa? Pierwsze recycler_viewpołączenie findViewByIdjest wykonywane i zapisywane w pamięci podręcznej .

Kevin Robatel
źródło
W najnowszej wersji otrzymuję ostrzeżenie, aby usunąć typ z <>. Ponieważ studio Android zmusza mnie do używania tylko operatora diamentu, <>gdy go używam, daje błąd.
Asif Mushtaq
46

Jesteś na poziomie API 26, gdzie typ powrót findViewByIdjest obecnie rodzajowy Tzamiast Viewa zatem można wywnioskować. Możesz zobaczyć odpowiedni dziennik zmian tutaj .

Więc powinieneś być w stanie to zrobić:

val recycler_view = findViewById<RecyclerView>(R.id.recycler_view)

Albo to:

val recycler_view: RecyclerView = findViewById(R.id.recycler_view)
zsmb13
źródło
7

W Kotlinmożemy uzyskać identyfikator widoku bez użycia findViewByIdskładni.

Na przykład używamy poniższego układu, z którego uzyskamy identyfikator widoku i wykonamy operację

Układ

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/welcomeMessage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="Hello World!"/>

</FrameLayout>

Jesteśmy w stanie znaleźć id widoku za pomocą poniższego kodu

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    welcomeMessage.text = "Hello Kotlin!" ////WE ARE GETTING THE IDS WITHOUT USING THE FINDVIEWBYID syntax
}

W JAKI SPOSÓB?

Aby móc z niego korzystać, potrzebujesz specjalnego importu (tego, który napiszę poniżej), ale IDE jest w stanie go zaimportować automatycznie. Nie może być prostsze!

import kotlinx.android.synthetic.main.YOUR_LAYOUT_NAME.*/// HERE "YOUR_LAYOUT_NAME" IS YOUR LAYOUT NAME WHICH U HAVE INFLATED IN onCreate()/onCreateView() 

Musimy zaimportować tę właściwość, aby uzyskać identyfikator widoku bez użycia findviewbyidskładni.

Więcej informacji na ten temat można znaleźć pod tym linkiem: - Kliknij tutaj

Ravindra Kushwaha
źródło
1
Genialne rozwiązanie! Bardzo mi pomogło!
gundrabur
7

Zwykle Kotlin może wywnioskować twój typ na podstawie informacji podanych w nawiasach.

W tym przypadku nie może, więc musisz to wyraźnie określić w ten sposób

findViewById<RecyclerView>(R.id.recycler_view)

Nie jestem jednak pewien typu, ale tak powinieneś go określić

Chciałbym dodać, że używając Anko , możesz jeszcze bardziej uprościć swój kod w ten sposób:

val recycler_view : RecyclerView =  find(R.id.recycler_view)
Alf Moh
źródło
4

Dodaj tę linię do swojego kodu jako Cokolwiek używasz kontrolera.

val tvHello = findViewById<TextView>(R.id.tvHello)
Najib Ahmed Puthawala
źródło
2

Możesz zignorować nadawanie identyfikatorów zmiennym w kotlin. Wystarczy użyć wtyczki

Wklej to w swoim gradle

 apply plugin: 'kotlin-android-extensions'

a wtedy nie musisz przypisywać identyfikatorów do var, możesz to zrobić tak jak

 recycler_view.setAdapter(youradapter);
Anmol317
źródło
Podaj powód odrzucenia głosu.
Anmol317,
1

Spróbuj tego:

Tutaj bindfunkcja ogólna służy do wiązania widoku. jego ogólna funkcja, której może używać w dowolnym widoku.

class MyActivity : AppCompatActivity() {
    private lateinit var recycler_view : RecyclerView
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        recycler_view = bind(R.id.recycler_view)
    }
}

fun <T : View> Activity.bind(@IdRes res : Int) : T {
    @Suppress("UNCHECKED_CAST")    
    return findViewById(res) as T
}
Mehul Kabaria
źródło
1
Pls, dodaj wyjaśnienie do swojego kodu. Odpowiedzi zawierające tylko kod są odradzane.
Willi Mentzel,
1
dodany. @WilliMentzel
Mehul Kabaria
0

Nie musisz nawet tworzyć obiektu, aby robić rzeczy z widokiem. Możesz po prostu użyć identyfikatora. Na przykład Kotlin

recycle_view.adapter = adapter

jest taki sam jak Java

RecycleView recycle_view = (RecycleView) findViewById(recycle_view);
recycle_view.setAdapter(adapter);
Ajay Sivan
źródło
0

Nie mogłem uzyskać dostępu do komponentów interfejsu użytkownika, takich jak OP, jak wygląda poniżej, był potrzebny w gradle aplikacji:

plugins {
    ...
    id 'kotlin-android-extensions'
}

Mimo że po dodaniu tej linii Android Studio nadal nie było w stanie automatycznie rozwiązać importu syntetyków kotlin, więc może być konieczne unieważnienie pamięci podręcznej i ponowne uruchomienie.

Jeśli nadal nie działa, zaimportuj ręcznie w zależności od widoków

  • widok aktywności / fragmentu: import kotlinx.android.synthetic.main. <your_activity_view>. *
  • normalne widoki: import kotlinx.android.synthetic.main. <your_layout_view> .view. *

Aktualizacja - 2

Jeśli otrzymujesz to ostrzeżenie informacyjne -

Ostrzeżenie: wtyczka Gradle „kotlin-android-extensions” jest przestarzała.

plugin 'kotlin-android-extensions' zostanie wycofany. Więc dodaj poniżej w swojej aplikacji

android {
    ...
    buildFeatures {
        viewBinding true
    }
}
Manti_Core
źródło