EditText输入后Fragment销毁时触发InputConnection空指针异常求助
我之前也碰到过完全一样的坑!这个空指针异常其实是输入法(IME)在Fragment已经销毁、对应的InputConnection变成null之后,还试图调用它的closeConnection()方法导致的。而且确实不是所有设备都会出现,这是因为不同厂商对输入法服务的实现或者系统View销毁的时序有细微差异,有些设备的IME会更及时地清理引用,有些则会延迟触发回调。
下面是几个经过验证的有效解决方案,你可以根据项目情况选择:
方案1:在Fragment销毁View前主动切断输入法连接
这是最直接且符合生命周期规范的方法,在Fragment的onDestroyView()中主动处理EditText的焦点并关闭软键盘,让IME提前清理掉InputConnection引用:
@Override public void onDestroyView() { super.onDestroyView(); EditText targetEditText = getView().findViewById(R.id.your_edit_text_id); if (targetEditText != null) { // 先清除EditText的焦点 targetEditText.clearFocus(); // 关闭软键盘 InputMethodManager imm = (InputMethodManager) requireContext().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(targetEditText.getWindowToken(), 0); } }
注意一定要在onDestroyView()里做,而不是onDestroy()——因为到onDestroy()时Fragment的View已经被销毁,getView()会返回null,拿不到EditText实例。
方案2:自定义EditText拦截无效的IME交互
如果方案1在某些特殊设备上还是没解决问题,可以试试自定义EditText,在View已经脱离窗口时,告诉IME这个控件不再是文本编辑器:
public class SafeEditText extends AppCompatEditText { public SafeEditText(Context context) { super(context); } public SafeEditText(Context context, AttributeSet attrs) { super(context, attrs); } public SafeEditText(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean onCheckIsTextEditor() { // 当View未附着到窗口或者窗口Token为空时,返回false if (!isAttachedToWindow() || getWindowToken() == null) { return false; } return super.onCheckIsTextEditor(); } }
然后把布局里的所有EditText替换成这个SafeEditText,这样Fragment销毁后,IME就不会再对这个控件发起InputConnection相关的调用了。
方案3:在宿主Activity统一处理(多Fragment场景)
如果你的App里多个Fragment都有这个问题,可以在宿主Activity的onPause()里统一处理当前焦点的EditText,避免每个Fragment重复写代码:
@Override protected void onPause() { super.onPause(); View currentFocusView = getCurrentFocus(); if (currentFocusView instanceof EditText) { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(currentFocusView.getWindowToken(), 0); currentFocusView.clearFocus(); } }
优先级建议
优先尝试方案1,这是最贴合系统设计的解决方式;如果某些设备还是出现问题,再结合方案2使用;方案3适合多个Fragment都有EditText的场景,能减少重复代码。
内容的提问来源于stack exchange,提问作者Scrobot

