Xamarin Forms EditableFactory Google Play测试崩溃问题排查
崩溃原因
- 直接触发点是
NoCopyEditableFactory.NewEditable中的强制转换逻辑:你默认所有传入的ICharSequence类型参数都实现了IEditable接口,直接写了(IEditable)source的强转,但这个前提不成立。 - 从错误堆栈可以看到,本次崩溃是Google Play测试环节的Espresso爬虫框架调用
ReplaceTextAction向输入框设置文本时触发的,该框架传入的source是普通非Editable类型的CharSequence(比如字符串包装实例、SpannableString等未实现IEditable的CharSequence实现),强转操作直接抛出System.InvalidCastException。 - 你实现这个自定义EditableFactory的初衷是避免系统默认Factory每次调用
setText时新建SpannableStringBuilder拷贝文本、丢失自定义Span,但直接强转的写法没有兼容所有输入场景,只要系统控件、测试框架、第三方库传入非Editable类型的CharSequence,就会触发崩溃。
修复方案
- 修正
NoCopyEditableFactory的转换逻辑,先判断传入source的实际类型:如果本身已经是IEditable实例就直接返回,保留你原本想要的避免无意义拷贝的效果;如果不是IEditable类型,就新建SpannableStringBuilder包装source返回,完全兼容所有CharSequence输入场景,和系统原生Factory的兼容逻辑对齐。
修正后的工厂类代码如下:private class NoCopyEditableFactory : EditableFactory { public override IEditable NewEditable(ICharSequence source) { if (source is IEditable existingEditable) { return existingEditable; } return new SpannableStringBuilder(source); } } - 额外修复现有代码的递归调用隐患:你在
Control_TextChanged回调中直接调用SetSpannable重新给控件设置文本,会再次触发TextChanged事件,容易引发死循环、重复渲染问题。可以增加一个标记位过滤自己主动触发的文本变更:private bool _isInternalSettingText; void SetSpannable(string text) { _isInternalSettingText = true; try { _spannable = new SpannableStringBuilder(text); // 原有设置Span的逻辑 // ... Control.SetText(_spannable, TextView.BufferType.Spannable); } finally { _isInternalSettingText = false; } } private void Control_TextChanged(object sender, Android.Text.TextChangedEventArgs e) { if (_isInternalSettingText) return; // 原有文本变更处理逻辑 // ... SetSpannable(newText); } - 记得在Renderer初始化完成、给Control设置EditableFactory的时候,传入你修正后的
NoCopyEditableFactory实例,不要漏了赋值。
内容的提问来源于stack exchange,提问作者jho
相关产品推荐
相关产品推荐

