在 Flutter 中,Controller 是用于管理特定 Widget 状态或行为的核心工具。以下是 Flutter 中常用 Controller 的分类详解及其典型应用场景:


一、核心 Controller 分类及功能

1. 文本输入控制

Controller

作用

常用场景

TextEditingController

控制 TextField/TextFormField的文本内容、选择和焦点

表单输入、实时搜索

FocusNode

管理输入框的焦点状态(获取/失去焦点)

表单跳转、键盘操作控制

示例代码​:

final _controller = TextEditingController();
final _focusNode = FocusNode();

TextField(
  controller: _controller,
  focusNode: _focusNode,
);
// 获取焦点
_focusNode.requestFocus(); 
// 清空输入
_controller.clear();

2. 滚动控制

Controller

作用

常用场景

ScrollController

监听/控制 ListView/GridView/ScrollView的滚动位置

滚动到指定位置、无限加载

PageController

控制 PageView的页面切换和动画效果

轮播图、引导页

TabController

管理 TabBarTabBarView的同步切换

顶部标签页

示例代码​:

final _scrollCtrl = ScrollController();
final _pageCtrl = PageController(initialPage: 0);

ListView(
  controller: _scrollCtrl,
  children: [...],
);
// 滚动到底部
_scrollCtrl.jumpTo(_scrollCtrl.position.maxScrollExtent);

3. 动画控制

Controller

作用

常用场景

AnimationController

驱动动画的播放、暂停、反向播放

自定义动画、复杂过渡效果

ScrollController

AnimatedBuilder结合实现滚动动画

视差滚动、动态特效

示例代码​:

final _animCtrl = AnimationController(
  vsync: this, // 需混入 SingleTickerProviderStateMixin
  duration: const Duration(seconds: 1),
);

Animation<double> animation = Tween(begin: 0, end: 1).animate(_animCtrl);
_animCtrl.forward(); // 启动动画

4. 路由与导航控制

Controller

作用

常用场景

NavigationController

管理页面堆栈和跳转逻辑(通常由框架自动处理)

深层链接、自定义路由

HeroController

控制 Hero动画的细节

页面间元素共享动画


5. 视频/音频播放控制

Controller

作用

常用场景

VideoPlayerController

控制视频播放、暂停、音量、进度等(需 video_player包)

视频播放器

AudioPlayerController

管理音频播放(需 audioplayers包)

音乐播放器、语音消息

示例代码​:

final _videoCtrl = VideoPlayerController.network('https://example.com/video.mp4');
await _videoCtrl.initialize(); // 必须初始化
_videoCtrl.play(); // 播放

6. 其他专用 Controller

Controller

作用

常用场景

TransformationController

控制 InteractiveViewer的缩放和平移

图片查看器、地图缩放

DraggableScrollableController

管理可拖动可滚动面板(如底部弹窗)

底部抽屉、可伸缩面板

RefreshController

管理下拉刷新和上拉加载(需 pull_to_refresh包)

分页列表


二、Controller 的通用生命周期管理

所有 Controller 必须遵循 ​创建 → 使用 → 销毁​ 的流程,避免内存泄漏:

class _MyPageState extends State<MyPage> {
  late final TextEditingController _textCtrl;
  late final ScrollController _scrollCtrl;

  @override
  void initState() {
    super.initState();
    _textCtrl = TextEditingController();
    _scrollCtrl = ScrollController();
  }

  @override
  void dispose() {
    _textCtrl.dispose(); // 必须销毁!
    _scrollCtrl.dispose();
    super.dispose();
  }
}

三、Controller 的进阶用法

1. 监听输入变化
_textCtrl.addListener(() {
  print('当前输入: ${_textCtrl.text}');
});
2. 实现滚动监听
_scrollCtrl.addListener(() {
  if (_scrollCtrl.position.pixels == _scrollCtrl.position.maxScrollExtent) {
    print('已滚动到底部');
  }
});
3. 动画序列控制
_animCtrl
  ..forward()
  ..then((_) => _animCtrl.reverse());

四、常见问题解决方案

Q1: Controller 何时需要手动销毁?​
  • 需要销毁​:TextEditingControllerScrollControllerAnimationController

  • 无需销毁​:由父 Widget 自动管理的 Controller(如 TabControllerDefaultTabController配合时)

Q2: 如何避免 setState()与 Controller 冲突?​
  • 在监听回调中调用 setState()前检查 mounted

    _controller.addListener(() {
      if (mounted) setState(() {});
    });
Q3: 如何实现多个 Controller 联动?​
  • 使用状态管理工具(如 Provider)共享状态:

    final tabCtrl = TabController(length: 3, vsync: this);
    final pageCtrl = PageController();
    
    tabCtrl.addListener(() {
      pageCtrl.animateToPage(tabCtrl.index, duration: kDuration, curve: Curves.ease);
    });

五、最佳实践建议

  1. 按需创建​:仅在需要时初始化 Controller

  2. 及时销毁​:在 dispose()中释放资源

  3. 单一职责​:每个 Controller 只管理一个核心功能

  4. 组合使用​:如 TextEditingController+ FocusNode实现完整输入控制

掌握这些 Controller 的使用,可以高效管理 Flutter 应用的交互和状态!

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐