android - extensions - No se puede "findViewById" en Kotlin. Obteniendo error "Inferencia de tipo fallida"
kotlin android extensions (9)
Recibo el siguiente error cuando intento encontrar un
RecycleView
por id.
Error: - Falló la inferencia de tipo: no hay suficiente información para inferir el parámetro T
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
}
}
Código: otra forma de hacerlo.
class KotlinActivity : AppCompatActivity() {
var recycler_view: RecyclerView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_kotlin)
recycler_view = findViewById<RecyclerView>(R.id.recycler_view)
}
}
Agregue esta línea para su código como lo que esté utilizando el controlador.
val tvHello = findViewById<TextView>(R.id.tvHello)
En
Kotlin
podemos obtener la identificación de la vista sin el uso de la sintaxis
findViewById
.
Por ejemplo, estamos utilizando el siguiente diseño a partir del cual 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 importarla 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 sintaxis
findviewbyid
.
Para obtener más información sobre este tema, consulte este enlace: - Haga clic aquí
Estás en el nivel 26 de API, donde el tipo de retorno de
findViewById
ahora es una
T
genérica en lugar de
View
y, por lo tanto, se puede inferir.
Puede ver el registro de cambios relevante
here
.
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)
Intenta algo como:
val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
También puedes usar
Kotlin Android Extensions
para eso.
Consulta el documento
here
.
Con él, puede llamar a
recycler_view
directamente en su código.
Extensiones de Android Kotlin:
-
En su aplicación,
gradle.build
agrega elapply plugin: ''kotlin-android-extensions''
-
En su clase, agregue import for
import kotlinx.android.synthetic.main.<layout>.*
Donde<layout>
es el nombre de archivo de su diseño. -
Eso es todo, puede llamar a
recycler_view
directamente en su código.
¿Como funciona?
La primera vez que llama a
recycler_view
, se realiza una llamada a
findViewById
y se
almacena en caché
.
Ni siquiera tiene que crear un objeto para hacer cosas con una vista. Puedes usar la identificación. Por ejemplo, Kotlin.
recycle_view.adapter = adapter
es lo mismo que Java
RecycleView recycle_view = (RecycleView) findViewById(recycle_view);
recycle_view.setAdapter(adapter);
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 sobre el 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)
Prueba esto:
Aquí
bind
utiliza la función genérica de vinculación para vincular la vista.
su función general se puede usar 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
}
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, simplemente puede hacerlo como
recycler_view.setAdapter(youradapter);