Overview
最近在适配iPad和安卓大屏时,发现项目中有个页面在滚动时频繁build,codeReview代码发现是该页面需要监听页面滚动更改顶部tabbar的颜色。
而在每次滚动的时候都会调用setState(() {});
,导致整个页面频繁刷新。
于是根据TextEditingController实现原理定制响应式控制的Widget来解决该问题,记录一下。
同时让AI生成了示例,便于理解,示例也在文档中。
TextEditingController 实现原理
TextEditingController 是 Flutter 中用于控制文本输入框内容的类,其核心原理如下:
ValueNotifier 基础:继承自 ValueNotifier<TextEditingValue>
,这意味着它是一个可观察的值,当值变化时会通知所有监听器。
文本状态管理:维护一个 TextEditingValue
对象,包含:
text
:当前文本内容
selection
:文本选择范围
composing
:输入法组合文本范围
双向绑定:
- 当用户在 TextField 中输入时,会更新 controller 的值
- 当通过代码修改 controller 的值时,会同步更新 TextField 显示
监听机制:通过 addListener
可以注册回调,当文本变化时执行相应操作
我们可以仿照 TextField 的实现原理,创建一个基于 ValueNotifier 的可观察 Widget:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| import 'package:flutter/material.dart';
class AlphaController extends ValueNotifier<double> { AlphaController({double alpha = 1.0}) : super(alpha.clamp(0.0, 1.0));
double get alpha => value; set alpha(double newAlpha) { value = newAlpha.clamp(0.0, 1.0); } }
class AlphaControlledWidget extends StatefulWidget { final AlphaController controller; final Widget child; const AlphaControlledWidget({ Key? key, required this.controller, required this.child, }) : super(key: key);
@override _AlphaControlledWidgetState createState() => _AlphaControlledWidgetState(); }
class _AlphaControlledWidgetState extends State<AlphaControlledWidget> { @override void initState() { super.initState(); widget.controller.addListener(_handleAlphaChange); }
@override void didUpdateWidget(AlphaControlledWidget oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.controller != widget.controller) { oldWidget.controller.removeListener(_handleAlphaChange); widget.controller.addListener(_handleAlphaChange); } }
@override void dispose() { widget.controller.removeListener(_handleAlphaChange); super.dispose(); }
void _handleAlphaChange() { setState(() {}); }
@override Widget build(BuildContext context) { return Opacity( opacity: widget.controller.alpha, child: widget.child, ); } }
|
使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| class AlphaDemo extends StatefulWidget { @override _AlphaDemoState createState() => _AlphaDemoState(); }
class _AlphaDemoState extends State<AlphaDemo> { final AlphaController _controller = AlphaController(alpha: 0.5);
@override Widget build(BuildContext context) { return Column( children: [ Slider( value: _controller.alpha, onChanged: (value) { _controller.alpha = value; }, ), AlphaControlledWidget( controller: _controller, child: Container( width: 200, height: 200, color: Colors.blue, child: Center( child: Text( '透明度控制', style: TextStyle(color: Colors.white, fontSize: 24), ), ), ), ), ], ); } }
|
实现原理分析
- AlphaController:类似于 TextEditingController,继承自 ValueNotifier,负责管理 alpha 值
- AlphaControlledWidget:类似于 TextField,监听 controller 的变化并更新 UI
- 响应式更新:当 controller 的值变化时,通过 setState 触发 Widget 重建
- 生命周期管理:正确处理了 controller 的监听器添加和移除
这种模式可以扩展到其他需要响应式控制的 Widget 属性,如大小、位置、颜色等。