问题描述
请考虑以下测试:
@Test
fun test() {
val s1 = SpannableString("Test")
val s2 = SpannableString("Test")
s1.setSpan(StyleSpan(BOLD),s1.length,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
s2.setSpan(StyleSpan(BOLD),s2.length,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
assertEquals(s1,s2)
}
它成功还是失败?
我的假设是它应该成功,但是失败(抓挠头)。在查看SpannableStringInternal
的实现时,我们看到该函数将每个范围与其对应范围进行比较(假设我们具有相等数量的范围)。
// Same as SpannableStringBuilder
@Override
public boolean equals(Object o) {
if (o instanceof Spanned &&
toString().equals(o.toString())) {
final Spanned other = (Spanned) o;
// Check span data
final Object[] otherSpans = other.getSpans(0,other.length(),Object.class);
final Object[] thisspans = getSpans(0,length(),Object.class);
if (mSpanCount == otherSpans.length) {
for (int i = 0; i < mSpanCount; ++i) {
final Object thisspan = thisspans[i];
final Object otherSpan = otherSpans[i];
if (thisspan == this) {
if (other != otherSpan ||
getSpanStart(thisspan) != other.getSpanStart(otherSpan) ||
getSpanEnd(thisspan) != other.getSpanEnd(otherSpan) ||
getSpanFlags(thisspan) != other.getSpanFlags(otherSpan)) {
return false;
}
} else if (!thisspan.equals(otherSpan) ||
getSpanStart(thisspan) != other.getSpanStart(otherSpan) ||
getSpanEnd(thisspan) != other.getSpanEnd(otherSpan) ||
getSpanFlags(thisspan) != other.getSpanFlags(otherSpan)) {
return false;
}
}
return true;
}
}
return false;
}
else if
中的第一个条件比较了Span对象是否相等,并且样式跨度(尽管编码相同的数据且类型相同)不相等,因为看起来StyleSpan
确实不覆盖等于。
为什么没有将这两者视为相等的特定原因,或者这是Android中的错误?
解决方法
由于StyleSpan(BOLD)
,它没有通过。 if(thisSpan == this)是false
,因为equals
中没有覆盖StyleSpan
。出于相同的原因,!thisSpan.equals(otherSpan)
是true
(if-else的第一个条件),因此是return false
。尝试将StyleSpan(BOLD)
分配给val
,并将相同的引用传递给两个SpannableStringBuilder
。它应该通过