Android Spanned, SpannedString, Spannable, SpannableString i CharSequence

96

Oferty android różnorodność interfejsów wszystko związane z tekstem i strun: Spanned, SpannedString, Spannable, SpannableStringi CharSequence.

Używałem wszystkich powyższych w różnych scenariuszach, zwykle po użyciu Html.fromHtml()do wyświetlania tekstu, który można połączyć w środku, TextVieww celu nadania mu stylu.

Próbowałem zrozumieć cel / użycie tych interfejsów na podstawie oficjalnej dokumentacji Androida i nie udało mi się, ponieważ jest to dość mylące. Jaki jest cel tych interfejsów? w jakich scenariuszach najczęściej się ich używa? W jakich przypadkach najlepiej ich unikać? Czy są jakieś oczywiste skutki, które należy wziąć pod uwagę podczas korzystania z któregokolwiek z nich?

Byłoby bardzo wdzięczne, gdyby ktokolwiek mógł udzielić rzetelnego wyjaśnienia.

woot
źródło

Odpowiedzi:

150

Jaki jest cel tych interfejsów?

diagram z yuml.me/edit/5f8da6cb CharSequenceto standardowy interfejs Java reprezentujący sekwencję znaków. Stringjest najczęściej używaną konkretną implementacją CharSequence, po której następuje StringBuilder.

Spannedjest CharSequencez „rozpiętościami” wskazującymi formatowanie, które należy zastosować do fragmentów tekstu, których rozpiętości nie można modyfikować.

Spannablejest Spanneddodaniem możliwości modyfikowania rozpiętości (dodawania lub usuwania formatowania), ale nie modyfikowania samego tekstu.

SpannedStringjest konkretną implementacją Spannedinterfejsu.

SpannableStringjest konkretną implementacją Spannableinterfejsu.

w jakich scenariuszach najczęściej ich używa się?

Kiedy istnieje metoda, która zwraca jedynkę (np. getText()Na a EditText) lub gdy istnieje metoda, która przyjmuje je jako parametr (np. setText()Na a TextView). diagram z yuml.me/edit/35c8f39f

Twój cytowany przypadek użycia Html.fromHtml()jest prawdopodobnie najbardziej powszechny w konwencjonalnym programowaniu na Androida, ponieważ a TextViewz a Spannedjest znacznie lżejszy niż WebView. Istnieją jednak inne przypadki użycia, takie jak:

W jakich przypadkach najlepiej ich unikać?

Są wyjątkowo okropne w walce z łysieniem, odśnieżaniem, naprawą pompy ciepła, robieniem sufletu itp.

:-)

Czy są jakieś oczywiste skutki, które należy wziąć pod uwagę podczas korzystania z któregokolwiek z nich?

Interfejsy z definicji nie mają „wpływu na wydajność” - stanowią jedynie opis interfejsu API.

Nie wiem, czy SpannableStringjest to znacznie wolniejsze niż SpannedStringprzy jakiejkolwiek konkretnej operacji. Jednak SpannableStringBuilder(co pozwala na manipulowanie tekstem oprócz rozpiętości formatu tego tekstu) może być nieco wolniejsze niż SpannableStringlub SpannedStringdo różnych rzeczy. Jednak to, czy różnice w wydajności mają znaczenie, zależy od użytkowania.

CommonsWare
źródło
4
Ponieważ oficjalna dokumentacja milczy, skąd masz te informacje? Ręczne przeglądanie źródeł w hardkorowy sposób?
Pacerier
11
@Pacerier: Nie jestem pewien, do jakiej części tej odpowiedzi masz na myśli. Na przykład hierarchia klas opisana w tej odpowiedzi z pewnością pochodzi z dokumentacji, a konkretnie z JavaDocs. I odwrotnie, brak przydatności tych rzeczy do zwalczania łysienia wynika z osobistych obserwacji.
CommonsWare
@CommonsWare, więc czy to oznacza, że ​​ciąg z emotikonami między nimi byłby uważany za, spannableStringa nie normalny ... ponieważ mam ogromne opóźnienie, setText(my_string) kiedy my_stringma w nim emotikony (jak w przypadku watsapp) w porównaniu do zwykłego ciągu. . (który ma tylko zwykły tekst) uprzejmie rzuć trochę światła ... jakoś uwierzyłem, że smilleys to nic innego jak tekst (Unicode)
eRaisedToX
1
@eRaisedToX: emotikony można zaimplementować jako emotikony lub obrazy. AFAIK, emoji byłyby pojedynczymi znakami Unicode i prawdopodobnie mogłyby znajdować się w zwykłym ciągu. Obrazy wymagałyby, ImageSpanco z kolei wymaga SpannableString.
CommonsWare,
Prawdopodobnie na pewno ... ale spróbuj poradzić sobie z emoji i używać zwykłych Ciągów, a wrócisz do walki z łysieniem. Editables i SpannableStringBuilders to Twoi najlepsi przyjaciele, jeśli chodzi o wdrażanie emotikonów. Zauważyłem, że chociaż tak, są po prostu unicode, tak kodujesz identyfikację zakresu emoji i ustawienie zakresu emoji, czyli tam, gdzie przychodzą twoje koszty wydajności. Uważaj, używając bibliotek emoji innych osób, jeśli nie wiesz jak oni funkcjonują ...
JamisonMan111
45

Strunowy

A Stringjest niezmienne (tj. Tekst nie może się zmienić). Nie ma też żadnych powiązanych z nim rozpiętości. (Rozpiętości to zakresy w tekście, które zawierają informacje dotyczące stylu, takie jak kolor, wyróżnienie, kursywa, łącza itp.) Możesz więc użyć znaku a, Stringgdy tekst nie wymaga zmiany i nie wymaga stylizacji.

StringBuilder

A StringBuilderma zmienny tekst, więc możesz go modyfikować bez tworzenia nowego obiektu. Jednak nie ma żadnych informacji o rozpiętości. To tylko zwykły tekst. Dlatego używaj a, StringBuildergdy musisz zmienić tekst, ale nie dbasz o stylizację.

SpannedString

A SpannedStringma niezmienny tekst (taki jak a String) i niezmienne informacje o rozpiętości. Jest to konkretna implementacja wymagań zdefiniowanych przez Spannedinterfejs. Użyj a, SpannedStringgdy twój tekst ma styl, ale nie musisz zmieniać ani tekstu, ani stylu po jego utworzeniu.

Uwaga: Nie ma czegoś takiego jak a, SpannedStringBuilderponieważ gdyby tekst się zmienił, informacja o rozpiętości prawdopodobnie również musiałaby ulec zmianie.

SpannableString

A SpannableStringma niezmienny tekst, ale jego informacje o rozpiętości są zmienne. Jest to konkretna implementacja wymagań zdefiniowanych przez Spannableinterfejs. Użyj a, SpannableStringgdy nie musisz zmieniać tekstu, ale styl tak.

SpannableStringBuilder

A SpannableStringBuilderma zmienny tekst i informacje o zakresie. Jest to konkretna implementacja wymagań zdefiniowanych przez interfejsy Spannablei Editable(między innymi). Użyj, SpannableStringBuildergdy będziesz musiał zaktualizować tekst i jego styl.

CharSequence

A CharSequenceto interfejs, a nie konkretna klasa. Oznacza to, że po prostu definiuje listę reguł, których należy przestrzegać dla każdej klasy, która go implementuje. I wszystkie wymienione powyżej klasy go implementują. Możesz więc użyć a, CharSequencegdy chcesz uogólnić typ obiektu, który masz, aby uzyskać maksymalną elastyczność. Można zawsze przygnębiony go na Stringlub SpannableStringBuilderlub cokolwiek później, jeśli zajdzie taka potrzeba.

Suragch
źródło
4
Doceniam sposób, w jaki przedstawiłeś swoją odpowiedź, bardzo łatwa do odczytania i zrozumienia, dzięki
JamisonMan111