TextInputClient currentTextEditingValue
Summary
Add a field, currentTextEditingValue
, to the TextInputClient
interface to get the current value of an editable text field
from a platform client.
Context
The TextInputClient
class is used by the Flutter framework to
communicate with platform code about the current state of text
input widgets like EditableText
.
The platform side can lose its state when an Android app
moves to the background. As of this change,
the app can ask the framework for the last known state.
In order to obtain this information,
the TextEditingValue
was surfaced for the TextInputClient
.
Description of change
On some supported platforms, the application can be moved into
the background where it is expected to consume fewer resources.
For example, a backgrounded application on Android should avoid consuming
unnecessary memory and has no need to retain references to views.
Before this change, the Android-specific platform code could
lose state information about editable text fields when
the app moved back to the foreground.
This is seen, for example,
when text entered in a TextField
widget is lost to
the Java code, but is still remembered in the Dart code.
As of this change,
the platform side now sends a textInput
channel
message called TextInput.requestExistingState
.
This notifies the Dart code that, when the app wakes up,
it should re-establish any text input connections
and notify the platform of its most
recently known editing state.
The TextInput
class interacts with client widgets using
the TextInputClient
interface. This interface previously
provided no insight into the current value that a client had.
To allow the TextInput
class to appropriately respond to
TextInput.requestExistingState
, a new getter was added to
TextInputClient
called currentTextEditingValue
.
You cannot safely use the last value passed to
TextInputConnection.setEditingState
, since the client
only calls that method under specific circumstances,
such as when Dart code directly modifies the value of a
TextEditingController
in a way that does not directly mirror
the platform’s native handling of a response to a key input event.
This is how a TextInputFormatter
generally works,
or what happens when Dart code directly sets
TextEditingController.value
.
Migration guide
If you previously implemented or extended TextEditingClient
,
you must now add the appropriate override for currentTextEditingValue
.
This value may be null.
If you want to migrate before this change lands, you can add a class to your class similar to the following:
abstract class _TemporaryTextEditingClient {
TextEditingValue get currentTextEditingValue;
}
This allows you to add the new member with an
@override
annotation before the change lands
in the framework. Later, you can remove the
temporary interface definition.
Code before migration:
class _MyCustomTextWidgetState extends State<MyCustomWidget> implements TextEditingClient {
...
@override
void updateEditingValue(TextEditingValue value) {
...
}
@override
void performAction(TextInputAction action) {
...
}
@override
void updateFloatingCursor(RawFloatingCursorPoint point) {
...
}
}
Code after migration:
class _MyCustomTextWidgetState extends State<MyCustomWidget> implements TextEditingClient {
...
@override
TextEditingValue get currentTextEditingValue => widget.textEditingController.value;
@override
void updateEditingValue(TextEditingValue value) {
...
}
@override
void performAction(TextInputAction action) {
...
}
@override
void updateFloatingCursor(RawFloatingCursorPoint point) {
...
}
}
Timeline
Landed in version: 1.16.3
In stable release: 1.17
References
API documentation:
Relevant issue:
Relevant PR: