配置更改时 TextInputLayout 的错误

Bug With TextInputLayout on Configuration Change

我在我的应用程序中使用 TextInputLayout,当我向它添加 TextWatcher 时,TextInputEditTextTextInputLayout 上设置了 error,当我触发配置更改时,我的应用程序崩溃了。

editText.addTextChangedListener(object : TextWatcher {
    override fun afterTextChanged(text: Editable) {
        // no-op
    }
    override fun beforeTextChanged(text: CharSequence, start: Int, count: Int, after: Int) {
        // no-op
    }
    override fun onTextChanged(text: CharSequence, start: Int, before: Int, count: Int) {
        textInputLayout.error = if (text.isBlank()) {
            getString(R.string.error_text)
        } else {
            null
        }
    }
})

堆栈跟踪是

java.lang.NullPointerException: Attempt to read from field 'int android.view.View.mViewFlags' on a null object reference at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3863) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3864) at com.google.android.material.textfield.TextInputLayout.dispatchRestoreInstanceState(TextInputLayout.java:2053) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3864) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3864) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3864) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3864) at android.view.View.restoreHierarchyState(View.java:19808) at androidx.fragment.app.Fragment.restoreViewState(Fragment.java:539) at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:907) at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238) at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303) at androidx.fragment.app.FragmentManagerImpl.dispatchStateChange(FragmentManagerImpl.java:2656) at androidx.fragment.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManagerImpl.java:2610) at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:246) at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:542) at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:201) at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1425) at android.app.Activity.performStart(Activity.java:7825) at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3294) at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221) at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201) at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) at android.os.Handler.dispatchMessage(Handler.java:107) at android.os.Looper.loop(Looper.java:214) at android.app.ActivityThread.main(ActivityThread.java:7356) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

看来您可能需要从那里覆盖 onViewStateRestored 和 remove/add 您的 TextWatcher

您还应该将 TextWatcher 保存在可以在配置更改(例如 Android ViewModel.

中保留的位置

这是一个简单的例子:

// Inside of onViewStateRestored

if (viewModel.textWatcher != null) {
    editText.removeTextChangedListener(viewModel.textWatcher)
    viewModel.textWatcher = null
}

// Create and add TextWatcher back