No se puede "findViewById" en Kotlin. Aparece el error "Error en la inferencia de tipos"


80

Recibo el siguiente error cuando intento encontrar un RecycleViewby id.

Error: - Error de inferencia de tipo: no hay suficiente información para inferir el parámetro T

Error

Código:

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
    }
}

Respuestas:


101

Prueba algo como:

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

Puedes usar Kotlin Android Extensionstambién para eso. Consulta el documento aquí .
Con él, puede llamar recycler_viewdirectamente en su código.

Extensiones de Android Kotlin:

  • En su aplicación gradle.buildagregueapply plugin: 'kotlin-android-extensions'
  • En su clase, agregue la importación para import kotlinx.android.synthetic.main.<layout>.*dónde <layout>está el nombre de archivo de su diseño.
  • Eso es todo, puede llamar recycler_viewdirectamente en su código.

¿Como funciona? La primera vez que llama recycler_view, se realiza una llamada a findViewByIdy se almacena en caché .


En la última versión, recibo una advertencia para eliminar el Tipo de <>. Como el estudio de Android me obliga a usar solo el operador de diamante <>cuando lo uso, está dando un error.
Asif Mushtaq

46

Estás en el nivel de API 26, donde el tipo de retorno de findViewByIdahora es genérico en Tlugar de Viewy, por lo tanto, se puede inferir. Puede ver el registro de cambios relevante aquí .

Entonces deberías poder hacer esto:

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

O esto:

val recycler_view: RecyclerView = findViewById(R.id.recycler_view)

7

En Kotlinpodemos obtener el id de la vista sin el uso de la findViewByIdsintaxis.

Por ejemplo, estamos usando el siguiente diseño del que obtendremos la identificación de la vista y realizaremos la operación

Diseño

<?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>

Podemos encontrar la identificación de la vista usando el siguiente código

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
}

¿CÓMO?

Para poder usarlo, necesita una importación especial (la que escribo a continuación), pero el IDE puede importarlo automáticamente. ¡No podría ser más fácil!

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

Necesitamos importar esta propiedad para obtener la identificación de la vista sin el uso de la findviewbyidsintaxis.

Para obtener más información sobre este tema, consulte este enlace: - Haga clic aquí


1
¡Solución brillante! ¡Me ayudo mucho!
gundrabur

7

Por lo general, Kotlin puede inferir su tipo utilizando la información proporcionada entre paréntesis.

En este caso, no puede, por lo que tendría que especificarlo explícitamente así

findViewById<RecyclerView>(R.id.recycler_view)

Sin embargo, no estoy muy seguro del tipo, pero así es como debe especificarlo.

Me gustaría agregar que, usando Anko , puede simplificar aún más su código de esta manera:

val recycler_view : RecyclerView =  find(R.id.recycler_view)

4

Agregue esta línea para su código como lo que esté usando controlador.

val tvHello = findViewById<TextView>(R.id.tvHello)

2

Puede ignorar dar identificadores a las variables en kotlin. Solo necesitas usar un complemento

Pega esto en tu gradle

 apply plugin: 'kotlin-android-extensions'

y luego no necesita asignar identificadores a var, puede hacerlo como

 recycler_view.setAdapter(youradapter);

Proporcione una razón para votar en contra.
Anmol317

1

Prueba esto:

Aquí la bindfunción genérica se usa para vincular la vista. su función general se puede utilizar para cualquier vista.

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
}

1
Por favor, agregue una explicación a su código. Se desaconsejan las respuestas con código únicamente.
Willi Mentzel

1
adicional. @WilliMentzel
Mehul Kabaria

0

Ni siquiera tiene que crear un objeto para hacer cosas con una vista. Puedes usar el id. Por ejemplo, Kotlin

recycle_view.adapter = adapter

es igual que, Java

RecycleView recycle_view = (RecycleView) findViewById(recycle_view);
recycle_view.setAdapter(adapter);

0

No pude acceder a los componentes de la interfaz de usuario, ya que OP se ve como se necesitaba a continuación dentro de la aplicación gradle:

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

A pesar de que después de agregar esta línea, Android Studio aún no pudo resolver automáticamente las importaciones de sintéticos kotlin, por lo que es posible que deba invalidar el caché y reiniciar.

Si aún no funciona, importe manualmente según las vistas

  • vista de actividad / fragmento: importar kotlinx.android.synthetic.main. <your_activity_view>. *
  • vistas normales: importar kotlinx.android.synthetic.main. <your_layout_view> .view. *

Actualización - 2

Si recibe esta advertencia de información:

Advertencia: El complemento de Gradle 'kotlin-android-extensions' está obsoleto.

El complemento 'kotlin-android-extensions' quedará obsoleto. Así que agregue a continuación en su aplicación gradle

android {
    ...
    buildFeatures {
        viewBinding true
    }
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.