Android ofrece una variedad de interfaces relacionadas con texto y cadenas: Spanned
, SpannedString
, Spannable
, SpannableString
y CharSequence
.
He usado todo lo anterior en varios escenarios usualmente después de usar Html.fromHtml()
para mostrar texto enlazable dentro de un TextView
para aplicarle un poco de estilo.
Intenté comprender el propósito / uso de estas interfaces a partir de la documentación oficial de Android y he fallado, ya que es bastante confuso. ¿Cuál es el propósito de estas interfaces? ¿En qué escenarios es más común usarlos? ¿En qué casos es mejor evitar usarlos? ¿Hay algún impacto obvio en el rendimiento que deba tenerse en cuenta al utilizar alguno de ellos?
Si alguien pudiera dar una explicación decente, sería muy apreciado.
¿Cuál es el propósito de estas interfaces?
CharSequence
es una interfaz Java estándar que representa una secuencia de caracteres. String
es la implementación concreta más comúnmente utilizada de CharSequence
, seguida de StringBuilder
.
Spanned
es una CharSequence
con “tramos” que indica que el formato se aplica a partes del texto, donde esos tramos no se pueden modificar.
Spannable
es un Spanned
, que agrega la capacidad de modificar los tramos (para agregar o quitar formato), pero no para modificar el texto en sí.
SpannedString
es una implementación concreta de la interfaz Spanned
.
SpannableString
es una implementación concreta de la interfaz Spannable
.
¿En qué escenarios es más común usarlos?
Cuando hay un método que devuelve uno (por ejemplo, getText()
en un EditText
) o cuando hay un método que toma uno como parámetro (por ejemplo, setText()
en un TextView
).
El caso citado de utilizar Html.fromHtml()
es quizás el más común en el desarrollo de Android convencional, ya que un TextView
con un Spanned
es mucho más ligero que un WebView
. Sin embargo, hay otros casos de uso, como:
Destacando los resultados de búsqueda
Permitir a los usuarios ingresar texto enriquecido y luego usar Html.toHtml()
para conservar ese texto formateado en una versión HTML
¿En qué casos es mejor evitar usarlos?
Son singularmente horribles en combatir la calvicie, la remoción de nieve, la reparación de la bomba de calor, hacer un soufflé, etc.
🙂
¿Hay algún impacto obvio en el rendimiento que deba tenerse en cuenta al utilizar alguno de ellos?
Las interfaces, por definición, no tienen “impactos en el rendimiento”: son simplemente una descripción de una API.
No estoy al tanto de que SpannableString
sea significativamente más lento que SpannedString
en una operación en particular. Sin embargo, SpannableStringBuilder
(que permite manipular el texto además de los tramos que formatean ese texto) bien puede ser un poco más lento que SpannableString
o SpannedString
para varias cosas. Sin embargo, si las diferencias de rendimiento son suficientes o no dependerá del uso.
Una String
es inmutable (es decir, el texto no puede cambiar). Tampoco tiene ningún tramo asociado. (Los espacios se extienden sobre el texto que incluyen información de estilo como color, resaltado, cursiva, enlaces, etc.). De modo que puede usar un String
cuando su texto no necesita ser modificado y no necesita ningún estilo.
Un StringBuilder
tiene texto mutable, por lo que puede modificarlo sin crear un nuevo objeto. Sin embargo, no tiene información de intervalo. Es solo texto simple Así que usa un StringBuilder
cuando necesites cambiar el texto, pero no te importa diseñarlo.
Un SpannedString
tiene texto inmutable (como una String
) y la información de tramo inmutable. Es una implementación concreta de los requisitos definidos por la interfaz Spanned
. Utilice SpannedString
cuando su texto tenga estilo, pero no necesita cambiar el texto o el estilo una vez creado.
Nota: No existe un SpannedStringBuilder
porque si el texto cambia, la información del intervalo también tendría que cambiar.
Un SpannableString
tiene texto inmutable, pero su información de extensión es mutable. Es una implementación concreta de los requisitos definidos por la interfaz Spannable
. Use SpannableString
cuando su texto no necesita ser cambiado, pero sí el estilo.
Un SpannableStringBuilder
tiene tanto texto mutable como información de tramo. Es una implementación concreta de los requisitos definidos por las interfaces Spannable
y Editable
(entre otras). Use un SpannableStringBuilder
cuando necesite actualizar el texto y su estilo.
Una CharSequence
es una interfaz y no una clase concreta. Eso significa que solo define una lista de reglas a seguir para cualquier clase que la implemente. Y todas las clases mencionadas anteriormente lo implementan. Entonces puede usar una CharSequence
cuando quiera generalizar el tipo de objeto que tiene para obtener la máxima flexibilidad. Siempre puedes SpannableStringBuilder
a String
o SpannableStringBuilder
o lo que sea más adelante si es necesario.