Android Spanned, SpannedString, Spannable, SpannableString e CharSequence

92

Ofertas Android uma variedade de interfaces todos relacionados com texto e strings: Spanned, SpannedString, Spannable, SpannableStringe CharSequence.

Usei todos os itens acima em vários cenários, geralmente depois de usar Html.fromHtml()para exibir texto vinculável dentro de um TextViewpara aplicar algum estilo a ele.

Eu tentei entender o propósito / uso dessas interfaces da documentação oficial do Android e falhei, pois é bastante confuso. Qual é o propósito dessas interfaces? em quais cenários é mais comum usá-los? Em que casos é melhor evitar usá-los? Há algum impacto óbvio no desempenho a ser considerado ao usar qualquer um deles?

Se alguém pudesse fornecer uma explicação decente, seria muito apreciado.

woot
fonte

Respostas:

148

Qual é o propósito dessas interfaces?

diagrama de yuml.me/edit/5f8da6cb CharSequenceé uma interface Java padrão que representa uma sequência de caracteres. Stringé a implementação concreta mais comumente usada de CharSequence, seguida por StringBuilder.

Spannedé um CharSequencecom "spans" indicando a formatação a ser aplicada a partes do texto, onde esses spans não podem ser modificados.

Spannableé um Spanned, adicionando a capacidade de modificar as extensões (para adicionar ou remover formatação), mas não para modificar o próprio texto.

SpannedStringé uma implementação concreta da Spannedinterface.

SpannableStringé uma implementação concreta da Spannableinterface.

em quais cenários é mais comum usá-los?

Quando há um método que retorna um (por exemplo, getText()em um EditText) ou quando há um método que leva um como parâmetro (por exemplo, setText()em a TextView). diagrama de yuml.me/edit/35c8f39f

Seu citado caso de uso Html.fromHtml()é talvez o mais comum no desenvolvimento convencional do Android, pois um TextViewcom a Spannedé muito mais leve do que um WebView. No entanto, existem outros casos de uso, como:

Em que casos é melhor evitar usá-los?

Eles são excepcionalmente terríveis no combate à calvície, remoção de neve, conserto de bombas de calor, fazer um suflê, etc.

:-)

Há algum impacto óbvio no desempenho a ser considerado ao usar qualquer um deles?

As interfaces, por definição, não têm "impactos no desempenho" - são apenas uma descrição de uma API.

Não estou ciente de que SpannableStringé significativamente mais lento do que SpannedStringem qualquer operação específica. No entanto, SpannableStringBuilder(o que permite manipular o texto além das extensões que formatam esse texto) pode muito bem ser um pouco mais lento do que SpannableStringou SpannedStringpara várias coisas. No entanto, se as diferenças de desempenho são suficientes ou não, dependerá do uso.

CommonsWare
fonte
4
Uma vez que os documentos oficiais são silenciosos, como você conseguiu essas informações? Navegando na fonte manual da maneira hardcore?
Pacerier
11
@Pacerier: Não tenho certeza a que parte desta resposta você está se referindo. Por exemplo, a hierarquia de classes descrita nesta resposta certamente vem da documentação, especificamente dos JavaDocs. Por outro lado, a falta de utilidade dessas coisas para combater a calvície vem da observação pessoal.
CommonsWare
@CommonsWare, isso significa que uma string com smileys entre eles seria considerada spannableStringnormal e não normal .. porque estou enfrentando uma grande defasagem com setText(my_string) quando my_stringtem smileys (como o de watsapp) em comparação com a string normal. . (que tem apenas texto simples) por favor, jogue alguma luz ... de alguma forma, eu acreditava que smilleys não são nada além de texto (unicode) apenas
eRaisedToX
1
@eRaisedToX: Smileys podem ser implementados como emoji ou imagens. AFAIK, emoji seriam caracteres Unicode individuais e provavelmente poderiam estar em uma string regular. As imagens exigiriam o ImageSpanque por sua vez exige SpannableString.
CommonsWare
Provavelmente com certeza ... mas tente lidar com emojis e usar cordas regulares e você estará de volta ao combate à calvície. Editáveis ​​e SpannableStringBuilders são seus melhores amigos quando se trata de implementar emojis. Descobri que, embora sejam simplesmente Unicode, é como você codifica a identificação do intervalo de emoji e a configuração do intervalo de emoji que é onde seu custo de desempenho está chegando. Tenha cuidado ao usar as Bibliotecas de emoji de outras pessoas, se você não souber como funcionam ...
JamisonMan111
43

Corda

A Stringé imutável (ou seja, o texto não pode ser alterado). Ele também não tem nenhum período associado a ele. (Spans são intervalos sobre o texto que incluem informações de estilo como cor, realce, itálico, links, etc.) Portanto, você pode usar um Stringquando seu texto não precisar ser alterado e não precisar de nenhum estilo.

StringBuilder

A StringBuildertem texto mutável, portanto, você pode modificá-lo sem criar um novo objeto. No entanto, ele não possui nenhuma informação de amplitude. É apenas um texto simples. Portanto, use um StringBuilderquando precisar alterar o texto, mas não se preocupe em estilizá-lo.

SpannedString

A SpannedStringtem texto imutável (como a String) e informações de amplitude imutáveis. É uma implementação concreta dos requisitos definidos pela Spannedinterface. Use um SpannedStringquando o seu texto tiver estilo, mas você não precisar alterar o texto ou o estilo após sua criação.

Nota: Não existe um SpannedStringBuilderporque, se o texto mudasse, as informações de amplitude provavelmente também teriam que mudar.

SpannableString

A SpannableStringpossui texto imutável, mas suas informações de amplitude são mutáveis. É uma implementação concreta dos requisitos definidos pela Spannableinterface. Use um SpannableStringquando seu texto não precisar ser alterado, mas o estilo sim.

SpannableStringBuilder

A SpannableStringBuildertem texto mutável e informações de extensão. É uma implementação concreta dos requisitos definidos pelas interfaces Spannablee Editable(entre outros). Use um SpannableStringBuilderquando precisar atualizar o texto e seu estilo.

CharSequence

A CharSequenceé uma interface e não uma classe concreta. Isso significa que apenas define uma lista de regras a seguir para qualquer classe que o implemente. E todas as classes mencionadas acima o implementam. Portanto, você pode usar a CharSequencequando quiser generalizar o tipo de objeto que possui para obter o máximo de flexibilidade. Você sempre pode fazer o downcast para um Stringou SpannableStringBuilderou qualquer outra coisa mais tarde, se necessário.

Suragch
fonte
3
Agradeço a maneira como você apresentou sua resposta, muito fácil de ler e entender, obrigado
JamisonMan111