Flutter 入門 - 狀態管理

黃馬發表於2018-06-23

Dart4Flutter - 01 – 變數、型別和函式

Dart4Flutter – 02 –控制流 和異常

Dart4Flutter – 03 – 類和泛型

Dart4Flutter – 04 – 非同步和庫

Dart4Flutter - 拾遺01 - flutter-dart環境搭建

Dart4Flutter - 不可變性

Flutter入門 - 狀態管理

Flutter 入門例項1

Flutter 入門 - Container 屬性詳解

Flutter 入門-本地訪問-MethodChannel

Flutter 例項 - 載入更多的ListView

Flutter 例項 - 從本地到Flutter通訊 - Event Channels

Flutter 入門 - 狀態管理

flutter是一個新的跨平臺框架,使用Dart語言開發。轉移到新的平臺,其中有一個問題:狀態管理。

  • 怎樣將狀態沿著元件向下傳遞
  • 狀態改變,怎麼樣重新整理UI
  • 怎樣在不同介面跳轉以及狀態同步

開始

因為我們要演示在不同的介面跳轉,所以現在我們建立兩個檔案MyHomePage.dartMySecondPage.dart .

我們例子具體如下:

  • 在MyHomePage增加counter的值
  • 跳轉到MySecondPage。
  • 在MySecondPage介面減少counter的值。

看起來似乎很簡單,但是我們要找到一個方法,可以使counter在兩個介面之間同步。

假設現在counter=0;當我們在MyHomePage將counter增加到2,然後跳轉到MySecondPage介面,顯示的counter也必須是2.

同時,假設我們在MySecondPage介面遞減兩次counter,這時當使用者跳轉到MyHomePage,counter也應該是0。

這就是狀態管理。

假設您已經知道setState()機制,用來更新UI的機制。現在我們看看具體怎麼做。

main.dart 如下:

import 'package:flutter/material.dart';
import 'package:flutter_redux_example/screens/MyHomePage.dart';
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
  
  @override
  _MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
  int counter;
  @override
  void initState() {
    super.initState();
    counter = counter ?? 0;
  }
  void _decrementCounter(_) {
    setState(() {
      counter--;
      print('decrement: $counter');
    });
  }
  
  void _incrementCounter(_) {
    setState(() {
      counter++;
      print('increment: $counter');
    });
  }
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(
        title: 'My Home Page',
        counter: counter,
        decrementCounter: _decrementCounter,
        incrementCounter: _incrementCounter,
      ),
    );
  }
}
複製程式碼

如上所示, _decrementCounter() 和 _incrementCounter()分別是遞增和遞減counter的方法,我們將他們當做MyHomePage的建構函式。

MyHomePage.dart 如下:

import 'package:flutter/material.dart';
import 'package:flutter_redux_example/screens/MySecondPage.dart';
class MyHomePage extends StatefulWidget {
  MyHomePage({
    Key key,
    this.title,
    this.counter,
    this.decrementCounter,
    this.incrementCounter
  }) : super(key: key);
  final String title;
  final int counter;
  final ValueChanged<void> decrementCounter;
  final ValueChanged<void> incrementCounter;
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
  void _onPressed() {
    widget.incrementCounter(null);
  }
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Text('You have pushed the button this many times:'),
            new Text(
              widget.counter.toString(),
              style: Theme.of(context).textTheme.display1,
            ),
            new RaisedButton(
              child: new Text('Next Screen'),
              onPressed: () {
                Navigator.push(
                  context,
                  new MaterialPageRoute(
                    builder: (context) => new MySecondPage(
                      widget.decrementCounter,
                      title: 'My Second Page',
                      counter: widget.counter,
                    ),
                  ),
                );
              },
            )
          ],
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: _onPressed,
        tooltip: 'Increment',
        child: new Icon(Icons.add),
      ),
    );
  }
}
複製程式碼

如上所示,我們將decrementCounter()作為MySecondPage建構函式的引數,向下傳遞。

MySecondPage.dart 檔案如下所示:

import 'package:flutter/material.dart';

class MySecondPage extends StatefulWidget {
  MySecondPage(
    this.decrementCounter, 
    {Key key, this.title, this.counter}
  ): super(key: key);
  final String title;
  final int counter;
  final ValueChanged<void> decrementCounter;
  @override
  _MySecondPageState createState() => new _MySecondPageState();
}
class _MySecondPageState extends State<MySecondPage> {
  void onPressed() {
    widget.decrementCounter(null);
  }
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Text('You have pushed the button this many times :'),
            new Text(
              super.widget.counter.toString(),
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
    floatingActionButton: new FloatingActionButton(
      onPressed: onPressed,
      tooltip: 'Decrement',
      child: new Icon(Icons.indeterminate_check_box),
      backgroundColor: Colors.red),
    );
  }
}
複製程式碼

總結

如果您瞭解react,上面的內容比較容易理解。

flutter中的StatefulWidgetStatelessWidget對應react中的ComponentPureComponent。flutter中稱為Widget的,react稱為Component

參考

相關文章