Cómo inicializar widgets en Android usando kotlin

Empecé a aprender usando el lenguaje kotlin en Android y tuve problemas al inicializar la variable de mi button, porque a la hora de definir mi variable me pide dar un valor inicial cuando inicializo con valor nulo y enlazar la variable en la function oncreate.

kotlin.KotlinNullPointerException

aquí está mi código

class AddsFragment : Fragment() { var Add: Button = null!! override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { val Rootview = inflater!!.inflate(R.layout.clubsfragment, null, false) Add = Rootview.findViewById(R.id.add) as Button return Rootview } } 

El !! los operadores verifican si el receptor es null y si arroja KotlinNullPointerException . ¡Tan null!! siempre lanzará una exception.

Puede lograr lo que quiere de las siguientes maneras:

  1. Establecer un tipo de propiedad para Button? . En este caso, al acceder a los methods del button, ¿tendrá que usar cualquiera ? o !! .

     var add: Button? = null // Initialize it somewhere. add?.setText("Text") // Calls setText if Add != null add!!.setText("Text") // Throws an exception if Add == null 
  2. Convierta el button en una propiedad lateinit .

     lateinit var add: Button 
  3. Convierta el button en una propiedad de delegado notNull .

     var add: Button by Delegates.notNull() 

En los dos últimos casos, no puede verificar si el button es null . Si necesita una comparación null para trabajar para la variable, use el primer enfoque.


Hay otros enfoques que no voy a describir en detalle en esta respuesta. El primero es usar extensiones de Kotlin para Android . Es un complemento de compilation que genera properties sintéticas para sus vistas, por lo que no necesita llamar a findViewById() y puede acceder a las vistas mediante el uso de properties generadas.

La segunda forma es crear su propio delegado que llamará a findViewById() por usted. Puede parecerse a esto:

 val add: Button by bindView(R.id.add) 

Puede encontrar un ejemplo de dicho delegado en el proyecto KotterKnife .

Puede usar Kotlin para escribir la function auxiliar de bind :

 fun <T : View> Activity.bind(@IdRes res : Int) : Lazy<T> { @Suppress("UNCHECKED_CAST") return lazy { findViewById(res) as T } } 

Luego, simplemente puede definir su variable una vez que use val (que es igual a la final en Java):

 class MyActivity : AppCompatActivity() { private val button: Button by bind(R.id.button) } 

o

 class MyActivity : AppCompatActivity() { private val button by bind<Button>(R.id.button) } 

Puedes inicializar vistas en kotlin usando cualquiera de los siguientes methods:

1. vars Nullable

 private var textView: TextView? = null … textView = findViewById(R.id.text_view) as TextView 

2. lateinit

 private lateinit var textView: TextView … textView = findViewById(R.id.text_view) as TextView 

3. Delegates.notNull ()

 private var textView: TextView by Delegates.notNull() … textView = findViewById(R.id.text_view) as TextView 

4. Propiedades perezosas

 private val textView: TextView by lazy { findViewById(R.id.text_view) as TextView } 

5. Navaja

 @BindView(R2.id.text_view) internal lateinit var textView: TextView 

6. Kotterknife

 private val textView: TextView by bindView(R.id.text_view) 

7. Extensiones de Kotlin para Android

Sin muestra de código, solo agregue las importaciones correctas y comience a usar las properties sintéticas generadas, como se muestra a continuación.

 import kotlinx.android.synthetic.main.<layout>.* 

8. Enlace de datos de Android

 binding = FragmentLayoutBinding.inflate(inflater, container, false) ... binding.textView.text = "Hello" 

Puede verificar pro / contras de cada método en Pros / cons de Android ver estrategias de acceso