為什么要單獨把這個異常拿出來說铐拐,因為這個異常出現(xiàn)的比較詭異徘键,先看拋出的異常,如下圖:
上圖是在華為兼容測試里面生成的遍蟋,出現(xiàn)這個問題的原因有三種:
1吹害、可能是下標計算有誤,導(dǎo)致start和end負值虚青;
2它呀、手機開啟無障礙模式的TalkBack功能,如果start==end也會;
3钟些、實現(xiàn)ClickableSpan時為了解決內(nèi)存泄漏問題烟号,按照網(wǎng)上的方法實現(xiàn)了NoCopySpan。部分機型可能不支持NoCopySpan的實現(xiàn)政恍,導(dǎo)致異常報錯,去除后恢復(fù)正常达传。
本人出現(xiàn)的問題是第二種篙耗,圖中可以看出有無障礙模式的api(即?Accessibility)。正常測試的話是無法發(fā)現(xiàn)這個問題的宪赶。當上線通過渠道遍歷測試則會爆出這個異常宗弯。先查看源碼找到SpannableStringBuilder中的checkRange方法,如圖2:
按理說怎么可能start和end都小于0呢搂妻,而且當start==end 也報 setSpan(-1...-1)starts before0,崩潰產(chǎn)生在輔助功能開啟后,關(guān)鍵錯誤代碼 是 android.view.accessibility.AccessibilityNodeInfo.setText(AccessibilityNodeInfo.java:2645)
查看源碼,如圖3:
private IdentityHashMap<Object,Integer>? mIndexOfSpan;
public intget SpanStart(Objectwhat){
if(mIndexOfSpan==null) return-1;
Integeri=mIndexOfSpan.get(what);
returni==null?-1:resolveGap(mSpanStarts[i]);
}
當mIndexOfSpan==null時蒙保,返回-1,所以
int? ?spanToReplaceStart? =spannable.getSpanStart(span);
int? ? spanToReplaceEnd? =spannable.getSpanEnd(span);
都返回-1欲主;
修改方法:
根據(jù)源碼來看 mIndexOfSpan 不為空即可解決
SpannableString s =new SpannableString(destStr);
s.setSpan(clickSpan,start,end,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textview.setText(s);
替換成
SpannableStringBuilderspan? ?Str? = SpannableStringBuilder.valueOf(destStr);
?spanStr.setSpan(clickSpan,start,end,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textview.setText(spanStr);
測試結(jié)果:
通過