溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Flutter組件狀態(tài)管理的方法有哪些

發(fā)布時(shí)間:2022-03-24 11:05:26 來源:億速云 閱讀:155 作者:小新 欄目:開發(fā)技術(shù)

這篇文章主要為大家展示了“Flutter組件狀態(tài)管理的方法有哪些”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Flutter組件狀態(tài)管理的方法有哪些”這篇文章吧。

前言

前面講了Flutter布局,布局只是靜態(tài)的。在Flutter中,組件分為StatelesslWidget和StatefulWidget。

  • StatelesslWidget

沒有狀態(tài),是一成不變的。比如圖標(biāo),文字,按鈕等

  • StatefulWidget

有狀態(tài)的組件,頁面數(shù)據(jù)是動態(tài)的,或者會隨著用戶操作變化,比如多選框,文本輸入框等。

有狀態(tài)組件

重點(diǎn)來了,如何使用實(shí)現(xiàn)一個(gè)有狀態(tài)的組件呢?

  • 有狀態(tài)的組件一般由兩個(gè)類構(gòu)成,一個(gè)StatefulWidget子類和一個(gè)State子類.

  • State類包含了組件的build()方法,并且負(fù)責(zé)維護(hù)組件狀態(tài)

  • 當(dāng)這個(gè)組件的狀態(tài)變化了,可以調(diào)用setState()方法來刷新頁面

狀態(tài)管理

由誰來負(fù)責(zé)狀態(tài)管理呢?是組件本身,還是他的父類,兩者都有又或是其他對象?答案是都可以。也就是說有三種方法實(shí)現(xiàn)狀態(tài)管理:

1.組件自己管理自己的狀態(tài)
2.組件的父組件管理狀態(tài)
3.混搭管理

那么如何決定該用那種方式來進(jìn)行狀態(tài)管理呢?一般來講有以下原則:

1.如果是用戶數(shù)據(jù),比如多選框是否被選中,一般是由選擇第2種方法
2.如果動效,比如放大縮小,那一般用第1種方法

PS:如果你實(shí)在迷芒,就直接選擇用第2種方法,用父類管理狀態(tài)。

舉例

組件自己管理自己的狀態(tài)

如下代碼:_TapboxAState這個(gè)State子類為TapboxA維護(hù)狀態(tài),內(nèi)部定義了一個(gè)_active變量來決定當(dāng)前是否為激活的狀態(tài),內(nèi)部還定義了一個(gè)_handleTap()回調(diào)函數(shù),來處理用戶點(diǎn)擊后的邏輯,并且調(diào)用了setState()生命周期方法,重新刷新頁面。

import 'package:flutter/material.dart';

// TapboxA 自己管理狀態(tài)
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(),
        ),
      ),
    );
  }
}

父組件管理狀態(tài)

更多時(shí)候我們需要父組件來決定子組件什么時(shí)候來更新狀態(tài),子組件只需要根據(jù)父組件傳過來的參數(shù)進(jìn)行合理的展示即可。這種情況下子組件并不需要維護(hù)狀態(tài),所以子組件是一個(gè)StatelessWidget,父組件ParentWidget才是StatefulWidget。代碼如下:
父組件維護(hù)了一個(gè)_active變量用來標(biāo)記是否為激活狀態(tài),并且實(shí)現(xiàn)了回調(diào)函數(shù)_handleTapboxChanged用來反轉(zhuǎn)激活狀態(tài),供子組件調(diào)用。子組件TapboxB是一個(gè)無狀態(tài)組件,只需要在被點(diǎn)擊的時(shí)候通知父組件來管理狀態(tài)。

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(),

        ),
      ),
    );
  }
}

混搭管理

混搭管理狀態(tài),就是因?yàn)橛行┣闆r下我們需要父組件管理一部分狀態(tài),子組件獨(dú)立管理另一部分狀態(tài)。在本次,我們根據(jù)上例添加一個(gè)動效,按鈕按下時(shí)要顯示高亮狀態(tài)(前文講過,動效一類的狀態(tài)一般要組件本身管理),抬起時(shí)取消高亮。
如下代碼:ParentWidget負(fù)責(zé)維護(hù)_active狀態(tài)來標(biāo)志是否被激活,子組件TapboxC負(fù)責(zé)維護(hù)_highlight狀態(tài)用來控制是否高亮顯示。

Flutter組件狀態(tài)管理的方法有哪些

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(),

        ),
      ),
    );
  }
}

當(dāng)然你也可以把高亮顯示的狀態(tài)交給父組件來管理,但是當(dāng)你開發(fā)完這個(gè)組件交給同事來用的時(shí)候,別人可能只會關(guān)注業(yè)務(wù)邏輯上的處理,不會關(guān)注的動效處理。

其他交互組件

Flutter內(nèi)部預(yù)置了很多交互組件,甚至還有IOS風(fēng)格的組件,都可以拿來用。如果有必要的話,可以向上面的例子一樣自定義組件使用。

以上是“Flutter組件狀態(tài)管理的方法有哪些”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI