android - usar - ¿Cómo funciona la sintaxis de acceso a las propiedades de Kotlin para las clases de Java(es decir, EditText setText)?
para que usar kotlin (4)
Estoy tratando de cambiar mi proyecto de Android a Kotlin. Tengo un texto de EditText
(una subclase de TextView
) para el que quiero establecer una sugerencia y un texto mediante programación. La pista funciona como se esperaba. Sin embargo, para el texto, obtengo una excepción de falta de coincidencia de tipo si trato de hacerlo utilizando la sintaxis del configurador Kotlin:
val test = EditText(context)
test.setHint("hint") // Lint message: "Use property access syntax"
test.hint = "hint" // ok
test.setText("text") // ok (no lint message)
test.text = "text" // Type mismatch: inferred type is kotlin.String but android.text.Editable! was expected
Si observamos la declaración, encontraremos firmas idénticas heredadas de TextView
:
public final void setHint(CharSequence hint)
public final void setText(CharSequence text)
Tuve la impresión de que xy = z
era un atajo para x.setY(z)
pero aparentemente esa impresión era incorrecta. setText()
se trata como un método normal en lugar de un definidor, pero ¿cuál es la diferencia entre estos dos métodos que hace que el compilador se comporte de manera diferente? El único en el que puedo pensar es que TextView
tiene una propiedad mHint
, pero no creo que sea así.
Otra cosa que no entiendo bien es, ¿de dónde viene android.text.Editable
? No hay un método setText(Editable)
, ni hay un campo público de este tipo.
Gracias.
Al generar una propiedad sintética para un par de getter / setter de Java, Kotlin primero busca un getter. El captador es suficiente para crear una propiedad sintética con un tipo de captador. Por otro lado, la propiedad no se creará si solo se presenta un setter.
Cuando un colocador entra en juego, la creación de propiedades se vuelve más difícil. La razón es que el getter y el setter pueden tener un tipo diferente. Además, el captador y / o el configurador pueden ser anulados en una subclase.
En su caso, la clase TextView
contiene un CharSequence getText()
y un setter void setText(CharSequence)
. Si tuviera una variable de tipo TextView
su código funcionaría bien. Pero tienes una variable de tipo EditText
. Y la clase EditText
contiene un getter Editable getText()
, lo que significa que puede obtener un Editable
para un EditText
y establecer un Editable
en un EditText
. Por lo tanto, Kotlin crea razonablemente un text
de propiedad sintética de tipo Editable
. La clase String
no es Editable
, por eso no puede asignar una instancia de String
a la propiedad de text
de la clase EditText
.
Alternativamente puedes escribir una extensión:
fun String.toEditable(): Editable = Editable.Factory.getInstance().newEditable(this)
Entonces puedes usarlo como tal:
mEditText.text = myString.toEditable()
El getText()
android.text.Editable
proviene de getText()
. Me parece que la resolución de obj.text = value
en Kotlin es un proceso de 2 pasos.
- El compilador intenta encontrar una propiedad de
text
o un método JavagetText
desde el cual infiere el tipo de propiedad - Para el tipo de propiedad inferida, el compilador intenta encontrar el establecedor de propiedad correspondiente o el método Java
setText(PropertyType value)
Dado que en el 1. el tipo inferido es Editable
el editText.text = "value"
falla con error de Type mismatch
.
Para evitar la falta de coincidencia de tipos, puede utilizar la clase interna Factory de la clase Editable. Así que ahora puedes hacer algo como:
textview.text = Editable.Factory.getInstance().newEditable("your text")