You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:41:27