当开启无障碍模式,setSpan (-1 ... -1) starts before 0

为什么要单独把这个异常拿出来说,因为这个异常出现的比较诡异,先看抛出的异常,如下图:

图1

上图是在华为兼容测试里面生成的,出现这个问题的原因有三种:

1、可能是下标计算有误,导致start和end负值;

2、手机开启无障碍模式的TalkBack功能,如果start==end也会;

3、实现ClickableSpan时为了解决内存泄漏问题,按照网上的方法实现了NoCopySpan。部分机型可能不支持NoCopySpan的实现,导致异常报错,去除后恢复正常。

本人出现的问题是第二种,图中可以看出有无障碍模式的api(即 Accessibility)。正常测试的话是无法发现这个问题的。当上线通过渠道遍历测试则会爆出这个异常。先查看源码找到SpannableStringBuilder中的checkRange方法,如图2:

图2

按理说怎么可能start和end都小于0呢,而且当start==end 也报 setSpan(-1...-1)starts before0,崩溃产生在辅助功能开启后,关键错误代码 是 android.view.accessibility.AccessibilityNodeInfo.setText(AccessibilityNodeInfo.java:2645)

查看源码,如图3:

图3

private IdentityHashMap  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;

修改方法:

根据源码来看 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);

测试结果:

通过

你可能感兴趣的:(当开启无障碍模式,setSpan (-1 ... -1) starts before 0)