Android Spanned,SpannedString,Spannable,SpannableString和CharSequence


92

Android提供了多种接口相关的所有文字和字符串: SpannedSpannedStringSpannableSpannableStringCharSequence

为了在其中显示可链接的文本,以便对其应用某些样式,通常在各种情况下使用以上所有内容。Html.fromHtml()TextView

我试图从Android的官方文档中了解这些接口的用途/用途,但由于它很混乱而失败了。这些接口的用途是什么?在哪些情况下最常使用它们?在哪种情况下最好避免使用它们?使用其中任何一种时,是否要考虑任何明显的性能影响?

如果有人能提供一个体面的解释,将不胜感激。

Answers:


148

这些接口的目的是什么?

来自yuml.me/edit/5f8da6cb的图表 CharSequence是表示字符序列的标准Java接口。String是的最常用的具体实现CharSequence,其次是StringBuilder

SpannedCharSequence带有“ spans”的,表示要应用于文本部分的格式,在这些部分中不能修改这些范围。

Spannable是一个Spanned,可以修改跨度(添加或删除格式),但不能修改文本本身。

SpannedStringSpanned接口的具体实现。

SpannableStringSpannable接口的具体实现。

在哪些情况下最常使用它们?

当有一个方法返回一个值时(例如,getText()在上EditText),或者当有一个方法将返回值一时(例如,在setText()TextView)。 yuml.me/edit/35c8f39f中的图表

您引用使用情况Html.fromHtml()也许是传统的Android开发中最常见的,作为TextView一个Spanned在重量上要轻得多比是WebView。但是,还有其他用例,例如:

在哪种情况下最好避免使用它们?

他们在对抗秃头,除雪,热泵维修,制作蛋奶酥等方面非常糟糕。

:-)

使用其中任何一种时,是否要考虑任何明显的性能影响?

根据定义,接口不具有“性能影响”,它们只是对API的描述。

我不知道这SpannableStringSpannedString任何特定操作都要慢得多。然而,SpannableStringBuilder(它允许在除跨度该格式文本操纵文本)可能是一个比特慢于SpannableStringSpannedString关于各种东西。但是,性能差异是否足够重要,取决于使用情况。


4
由于官方文档保持沉默,因此您是如何获得这些信息的?手工源码浏览的铁杆方式?
Pacerier,2014年

11
@Pacerier:我不确定您指的是该答案的哪一部分。例如,此答案中描述的类层次结构肯定来自文档,特别是JavaDocs。相反,这些东西在对抗脱发方面缺乏实用性是由于个人观察。
CommonsWare,2014年

@CommonsWare,这是否意味着在中间带有笑脸的字符串将被视为a spannableString而不是正常的字符串..因为与普通字符串相比,setText(my_string) 当when中my_string带有笑脸(如watsapp)时,我面临巨大的滞后。 。(其中只有纯文本)请给我一些启示……我以某种方式相信笑脸只不过是文本(unicode)而已
eRaisedToX

1
@eRaisedToX:笑脸可以实现为表情符号或图像。AFAIK,表情符号将是单个Unicode字符,并且大概可以是常规字符串。图片需要ImageSpan,而图片又需要SpannableString
CommonsWare

大概可以肯定...但是尝试处理表情符号并使用常规字符串,您将立即摆脱秃顶。当实现表情符号时,Editables和SpannableStringBuilders是您最好的朋友。我发现,虽然它们只是unicode,但是这是您如何编码表情符号跨度的标识和表情符号跨度的设置的代码,这是性能成本的来源。如果您不知道,请谨慎使用其他人的表情符号库它们是如何工作的……
JamisonMan111 '18

43

A String是不可变的(即文本不能更改)。它也没有任何关联的跨度。(跨度是文本上的范围,其中包括样式信息,如颜色,突出显示,斜体,链接等。)因此,String当您的文本不需要更改且不需要任何样式时,可以使用a 。

StringBuilder

一个StringBuilder具有可变文本,这样你就可以修改它,而无需创建一个新的对象。但是,它没有任何跨度信息。这只是纯文本。因此,StringBuilder当您需要更改文本但不关心样式设置时,请使用a 。

SpannedString

一个SpannedString具有不可改变的文本(像String)和不可变跨度信息。它是Spanned接口定义的需求的具体实现。SpannedString当文本具有样式但在创建后无需更改文本或样式时,请使用a 。

注意:根本没有a之类的东西,SpannedStringBuilder因为如果文本更改了,那么跨度信息也很有可能必须更改。

SpannableString

一个SpannableString具有不可改变的文字,但它的跨度信息是可变的。它是Spannable接口定义的需求的具体实现。SpannableString当您的文本不需要更改但样式需要更改时,请使用a 。

SpannableStringBuilder

A SpannableStringBuilder具有可变的文本和跨度信息。它是Spannableand Editable接口(以及其他接口)定义的需求的具体实现。使用SpannableStringBuilder时,你将需要更新的文本,它的风格。

字符序列

A CharSequence是接口,而不是具体的类。这意味着它只定义了实现它的任何类要遵循的规则列表。上面提到的所有类都实现了它。因此,CharSequence当您要泛化具有最大灵活性的对象类型时,可以使用a 。如有需要,您随时可以将其转换为StringSpannableStringBuilder或其他任何格式。


3
非常感谢您表达自己的回答的方式,非常易于阅读和理解,谢谢
JamisonMan111
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.