持续创作,加速成长!这是我参与「日新计划 6 月更文挑战」的第3天,点击查看活动详情。

问题

在做搜索输入框时,用户输入文本之后,用户如果想更改搜索内容那么我们都会有一个手动清空数据的按钮,在清空数据时,在onChanged(text)回调中没有收到回调。

js输入框

我们先看下问题代码,如果调用_controller.clear();清空数据,那么在onChanged里是接受不到回调的。为什么会出现这种情况,这就需要我们去查看下源码了。
示例代码:

TextEditingController _controller = TextEditingController();
TextField(
  cursorColor: Colors.blue,
  controller: _controller,
  autocorrect: true,
  onChanged: (text){
    print("onChanged:$text");
  },
  decoration: InputDecoration(
      labelText: "关键字",
      hintText: "请输入内容",
      suffixIcon: InkWell(
        child: Icon(Icons.close),
        onTap: (){
          _controller.clear();
        },
      ),
      // icon: Icon(Icons.add),
      hintStyle: TextStyle(color: Colors.grey)),
   ),

我们点进去onChanged的源码进去看下,

Flutter更改输入框内容,onChanged接受不到回调?

我们可以看到这么一句话,意思是说,这个回调是专门针对输入的更改通知,那么为什么我们通过控制器更改数据就接受不到呢?通过控制器改变文本难道和键盘输入改变不源码编程器一样吗?带着这俩问题我们一起往下看。 接着微信输入框往下看这个回调是在哪里实现的,可以看到返回接口英文EditableText组件并在这个组件里传递了这个参数源码时代EditableText也是一个基本的输入框控件,通常在Flutter中我们不直接使用他。

child: EditableText(
  // Only show the selection highlight when the text field is focused.
  selectionColor: focusNode.hasFocus ? selectionColor : null,
 /// 省略...
  onChanged: widget.onChanged,

继续点进去E输入框变小了怎么恢复ditableText,在2488行我们发现了这个回调的实现,

Flutter更改输入框内容,onChanged接受不到回调?

部分源码:

@pragma('vm:notify-debugger-on-exception')
void _formatAndSetValue(TextEditingValue value, SelectionChangedCause? cause, {bool userInteraction = false}) {
  final bool textChanged = _value.text != value.text
                        || (!_value.composing.isCollapsed && value.composing.isCollapsed);
   // 略... ...
// Changes made by the keyboard can sometimes be "out of band" for listening
// components, so always send those events, even if we didn't think it
// changed. Also, the user long pressing should always send a selection change
// as well.
  if (textChanged) {
    try {
      widget.onChanged?.call(_value.text);
    } catch (exception, stack) {
      FlutterError.reportError(FlutterErrorDetails(
        exception: exception,
        stack: stack,
        library: 'widgets',
        context: ErrorDescription('while calling onChanged'),
      ));
    }
  }
}
/// 键盘更新数据触发
@override
void updateEditingValue(TextEditingValue value) {
 // 略... ...
    _formatAndSetValue(value, SelectionChangedCause.keyboard);
}

通过源码我们发现这个回调是通过updateEditingValue方法触发的,而这个方法是TextInputClient 抽象类里的方法,而这个方法官方说是从客户端输入文本接受信息的接口。到这里我们知输入框测试用例道了,这个回调是通过设备输入端更改状态触发,也就是在只有在键盘输入改变状态时才会触发这个方法。

abstract class TextInputClient {
void updateEditingValue(TextEditingValue value);
}

那么问题来了,通过控制器是如何触发改变文本的呢,首先我们看下控制器类,最终实现了ChangeNotifier类,并封装源码编辑器TextEditingValue数据类来进行保存更新,通过源码可以知道,里面不光有文本信息,还有文本范围等。

class ValueNotifier<T> extends ChangeNotifier implements ValueListenable<T> {}
class TextEditingController extends ValueNotifier<TextEditingValue> {}
class TextEditingValue {
  /// Creates information for editing a run of text.
  ///
  /// The selection and composing range must be within the text.
  ///
  /// The [text], [selection], and [composing] arguments must not be null but
  /// each have default values.
  const TextEditingValue({
    this.text = '',
    this.selection = const TextSelection.collapsed(offset: -1),
    this.composing = TextRange.empty,
  }) 

再回过头看源码网站下清除方法,可以看到,这里直接可以看到将 TextEditingValue的范围直接设置为0,并调用 super.value = newValue;方法,通知更新数据。
部分源码:

void clear() {
  value = const TextEditingValue(selection: TextSelection.collapsed(offset: 0));
}
@override
set value(TextEditingValue newValue) {
  assert(
    !newValue.composing.isValid || newValue.isComposingRangeValid,
    'New TextEditingValue $newValue has an invalid non-empty composing range '
    '${newValue.composing}. It is recommended to use a valid composing range, '
    'even for readonly text fields',
  );
  super.value = newValue;
}
set value(T newValue) {
  if (_value == newValue)
    return;
  _value = newValue;
  notifyListeners();
}

最终会通过renderObjecflutter开发的app有哪些t重新渲染数据完成fluttering输入框更新,从这里我们就知道通过控制器改变文本是不会走onCh源码交易平台anged回调的,因flutter框架onChanged回调只是设备键盘输入的监听,回到刚开始接口卡的注释,获取我们就理解了那句注释,which are more specializedflutter是什么意思 input change notificatflutteringions. 专门的输入更改通知。

Flutter更改输入框内容,onChanged接受不到回调?

我们如果想监听控制器改变数据的时候就可以通过给控制器添加 addListener 来进行监听,这里无论通过键盘输入还是通过控微信输入框制器改变文本都会接受到回调。addL接口和抽象类的区别istener不但会监听文本变化,并且当光标位置改变时也会触发等。

_controller.addListener(() {
  var text = _controller.text;
  var selection = _controller.selection;
  print("addListener text $text ");
  print("addListener selection $selection ");
});

结论

onChanged:只在设备键盘等输入改变时触发。
addListener:当文本框改变Teflutter菜鸟教程xtEditingValue里的任何内容接口和抽象类的区别都会收到回调。
无论通过键盘改源码编辑器下载变,还是通过控制器改变,最终重新渲染改变文本框的方式都是一样的,都是接口测试通过rendflutter是什么意思erObject重新渲染,只不过两个监听方法监听的内容qq输入框不一样而已。那本篇文章就到这结束了,希望对你有所帮助。如果有问题,欢迎评论指正~