配置更改时 TextInputLayout 的错误
Bug With TextInputLayout on Configuration Change
我在我的应用程序中使用 TextInputLayout
,当我向它添加 TextWatcher
时,TextInputEditText
在 TextInputLayout
上设置了 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
我在我的应用程序中使用 TextInputLayout
,当我向它添加 TextWatcher
时,TextInputEditText
在 TextInputLayout
上设置了 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