AutoCompleteTextView选择联系人时崩溃求助(API27模拟器)
解决API27下AutoCompleteContactTextView选择联系人时的崩溃问题
我之前在API27的模拟器上碰到过一模一样的拼写检查相关崩溃,咱们来拆解问题并解决它:
崩溃根源
从堆栈能看到,问题出在Android 8.1(API27)的SpellChecker组件上——当你连续调用setText(null)再setText(...)时,编辑器的内部文本状态还没同步完成,拼写检查器在解析文本时拿到了无效的偏移量-1,直接抛出异常。API24的拼写检查逻辑没这么严格,所以没触发这个问题。
具体解决方案
方案1:移除多余的setText(null)调用
你现在先清空文本再设置目标内容的操作完全没必要,反而会干扰编辑器状态。直接替换成:
@Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { selected = (People) getAdapter().getItem(position); GlobalVars.selectedPerson = selected; somethingIsSelected = true; String name = selected.getName() != null ? selected.getName().toString() : ""; // 直接设置文本,跳过setText(null) setText(name, TextView.BufferType.SPANNABLE); Log.d("Something Selected", String.valueOf(somethingIsSelected)); }
方案2:改用NORMAL/EDITABLE缓冲类型(如果不需要SPANNABLE特性)
如果你不需要保留 Spannable 文本的可编辑标记特性,直接换成NORMAL类型就能绕过拼写检查的这个bug:
setText(name, TextView.BufferType.NORMAL);
或者用EDITABLE,它的处理逻辑和SPANNABLE不同,但也能避免这个偏移量问题:
setText(name, TextView.BufferType.EDITABLE);
方案3:延迟设置文本,让编辑器状态稳定
如果必须使用SPANNABLE类型,用post()把setText操作放到主线程消息队列末尾,等编辑器完成上一次状态更新后再执行:
@Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { selected = (People) getAdapter().getItem(position); GlobalVars.selectedPerson = selected; somethingIsSelected = true; String name = selected.getName() != null ? selected.getName().toString() : ""; post(() -> { setText(name, TextView.BufferType.SPANNABLE); }); Log.d("Something Selected", String.valueOf(somethingIsSelected)); }
方案4:临时禁用拼写检查
可以在设置文本前后临时关闭拼写检查,设置完成后再恢复:
@Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { selected = (People) getAdapter().getItem(position); GlobalVars.selectedPerson = selected; somethingIsSelected = true; String name = selected.getName() != null ? selected.getName().toString() : ""; // 临时禁用拼写检查 setInputType(getInputType() | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); setText(name, TextView.BufferType.SPANNABLE); // 恢复原输入类型 setInputType(getInputType() & ~InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); Log.d("Something Selected", String.valueOf(somethingIsSelected)); }
验证建议
优先试方案1和方案2,这两个改动最小,也最容易解决问题。如果必须保留SPANNABLE,再用方案3或4。
内容的提问来源于stack exchange,提问作者Kristy Welsh
相关产品推荐
相关产品推荐

