您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“Flutter組件狀態管理的方法有哪些”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“Flutter組件狀態管理的方法有哪些”這篇文章吧。
前面講了Flutter布局,布局只是靜態的。在Flutter中,組件分為StatelesslWidget和StatefulWidget。
StatelesslWidget
沒有狀態,是一成不變的。比如圖標,文字,按鈕等
StatefulWidget
有狀態的組件,頁面數據是動態的,或者會隨著用戶操作變化,比如多選框,文本輸入框等。
重點來了,如何使用實現一個有狀態的組件呢?
有狀態的組件一般由兩個類構成,一個StatefulWidget子類和一個State子類.
State類包含了組件的build()
方法,并且負責維護組件狀態
當這個組件的狀態變化了,可以調用setState()
方法來刷新頁面
由誰來負責狀態管理呢?是組件本身,還是他的父類,兩者都有又或是其他對象?答案是都可以。也就是說有三種方法實現狀態管理:
1.組件自己管理自己的狀態
2.組件的父組件管理狀態
3.混搭管理
那么如何決定該用那種方式來進行狀態管理呢?一般來講有以下原則:
1.如果是用戶數據,比如多選框是否被選中,一般是由選擇第2種方法
2.如果動效,比如放大縮小,那一般用第1種方法
PS:如果你實在迷芒,就直接選擇用第2種方法,用父類管理狀態。
舉例
組件自己管理自己的狀態
如下代碼:_TapboxAState
這個State
子類為TapboxA
維護狀態,內部定義了一個_active
變量來決定當前是否為激活的狀態,內部還定義了一個_handleTap()
回調函數,來處理用戶點擊后的邏輯,并且調用了setState()
生命周期方法,重新刷新頁面。
import 'package:flutter/material.dart'; // TapboxA 自己管理狀態 void main() => runApp(const MyApp()); //------------------------- TapboxA ---------------------------------- class TapboxA extends StatefulWidget { const TapboxA({Key? key}) : super(key: key); @override _TapboxAState createState() => _TapboxAState(); } class _TapboxAState extends State<TapboxA> { bool _active = false; void _handleTap() { setState(() { _active = !_active; }); } @override Widget build(BuildContext context) { return GestureDetector( onTap: _handleTap, child: Container( child: Center( child: Text( _active ? 'Active' : 'Inactive', style: const TextStyle(fontSize: 32.0, color: Colors.white), ), ), width: 200.0, height: 200.0, decoration: BoxDecoration( color: _active ? Colors.lightGreen[700] : Colors.grey[600], ), ), ); } } //------------------------- MyApp ---------------------------------- class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', home: Scaffold( appBar: AppBar( title: const Text('Flutter Demo'), ), body: const Center( child: TapboxA(), ), ), ); } }
父組件管理狀態
更多時候我們需要父組件來決定子組件什么時候來更新狀態,子組件只需要根據父組件傳過來的參數進行合理的展示即可。這種情況下子組件并不需要維護狀態,所以子組件是一個StatelessWidget
,父組件ParentWidget
才是StatefulWidget
。代碼如下:
父組件維護了一個_active
變量用來標記是否為激活狀態,并且實現了回調函數_handleTapboxChanged
用來反轉激活狀態,供子組件調用。子組件TapboxB
是一個無狀態組件,只需要在被點擊的時候通知父組件來管理狀態。
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class ParentWidget extends StatefulWidget { const ParentWidget({Key? key}) : super(key: key); @override _ParentWidgetState createState() => _ParentWidgetState(); } class _ParentWidgetState extends State<ParentWidget> { bool _active = false; void _handleTapboxChanged(bool newValue) { setState(() { _active = newValue; }); } @override Widget build(BuildContext context) { return SizedBox( child: TapboxB( active: _active, onChanged: _handleTapboxChanged, ), ); } } //------------------------- TapboxB ---------------------------------- class TapboxB extends StatelessWidget { const TapboxB({ Key? key, this.active = false, required this.onChanged, }) : super(key: key); final bool active; final ValueChanged<bool> onChanged; void _handleTap() { onChanged(!active); } @override Widget build(BuildContext context) { return GestureDetector( onTap: _handleTap, child: Container( child: Center( child: Text( active ? 'Active' : 'Inactive', style: const TextStyle(fontSize: 32.0, color: Colors.white), ), ), width: 200.0, height: 200.0, decoration: BoxDecoration( color: active ? Colors.lightGreen[700] : Colors.grey[600], ), ), ); } } //------------------------- MyApp ---------------------------------- class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', home: Scaffold( appBar: AppBar( title: const Text('Flutter Demo'), ), body: const Center( // child: TapboxA(), child: ParentWidget(), ), ), ); } }
混搭管理
混搭管理狀態,就是因為有些情況下我們需要父組件管理一部分狀態,子組件獨立管理另一部分狀態。在本次,我們根據上例添加一個動效,按鈕按下時要顯示高亮狀態(前文講過,動效一類的狀態一般要組件本身管理),抬起時取消高亮。
如下代碼:ParentWidget
負責維護_active
狀態來標志是否被激活,子組件TapboxC
負責維護_highlight
狀態用來控制是否高亮顯示。
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class ParentWidget extends StatefulWidget { const ParentWidget({Key? key}) : super(key: key); @override _ParentWidgetState createState() => _ParentWidgetState(); } class _ParentWidgetState extends State<ParentWidget> { bool _active = false; void _handleTapboxChanged(bool newValue) { setState(() { _active = newValue; }); } @override Widget build(BuildContext context) { return SizedBox( child: TapboxC( active: _active, onChanged: _handleTapboxChanged, ), ); } } //----------------------------- TapboxC ------------------------------ class TapboxC extends StatefulWidget { const TapboxC({ Key? key, this.active = false, required this.onChanged, }) : super(key: key); final bool active; final ValueChanged<bool> onChanged; @override _TapboxCState createState() => _TapboxCState(); } class _TapboxCState extends State<TapboxC> { bool _highlight = false; void _handleTapDown(TapDownDetails details) { setState(() { _highlight = true; }); } void _handleTapUp(TapUpDetails details) { setState(() { _highlight = false; }); } void _handleTapCancel() { setState(() { _highlight = false; }); } void _handleTap() { widget.onChanged(!widget.active); } @override Widget build(BuildContext context) { return GestureDetector( onTapDown: _handleTapDown, // Handle the tap events in the order that onTapUp: _handleTapUp, // they occur: down, up, tap, cancel onTap: _handleTap, onTapCancel: _handleTapCancel, child: Container( child: Center( child: Text(widget.active ? 'Active' : 'Inactive', style: const TextStyle(fontSize: 32.0, color: Colors.white)), ), width: 200.0, height: 200.0, decoration: BoxDecoration( color: _highlight?Colors.lightGreen :widget.active ? Colors.lightGreen[700] : Colors.grey[600], ), ), ); } } //------------------------- MyApp ---------------------------------- class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', home: Scaffold( appBar: AppBar( title: const Text('Flutter Demo'), ), body: const Center( // child: TapboxA(), child: ParentWidget(), ), ), ); } }
當然你也可以把高亮顯示的狀態交給父組件來管理,但是當你開發完這個組件交給同事來用的時候,別人可能只會關注業務邏輯上的處理,不會關注的動效處理。
其他交互組件
Flutter內部預置了很多交互組件,甚至還有IOS風格的組件,都可以拿來用。如果有必要的話,可以向上面的例子一樣自定義組件使用。
以上是“Flutter組件狀態管理的方法有哪些”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。