Flutter局部刷新

在Flutter中,如果我們想要更新頁面中的某個widget的狀態的話,一般會使用setState方法重走build方法來刷新。當頁面佈局複雜的時候,這樣肯定是不行的。

下面提供了兩種局部刷新的方式,通過providerStreamBuilder來實現局部刷新

1、通過provider刷新

首先在pubspec.yaml中添加provider依賴

  # provider
  provider: ^3.1.0

下面通過provider來實現一個發送驗證碼的案例。

創建一個TimerModel文件

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';

class TimerModel extends ChangeNotifier{

  StreamSubscription _subscription;
  int _count = 0;///當前計數

  int get count => 10 - _count;///剩餘時間

  _setCount(){
    _count++;
    notifyListeners();
  }

  startTimer(){
    _count = 0;
    _subscription = Observable.periodic(Duration(seconds: 1))
        .startWith(10)
        .take(10)
        .listen((t){
        _setCount();
    });
  }

  @override
  void dispose() {
    _subscription?.cancel();
    super.dispose();
  }
}

頁面佈局如下:

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("短信倒計時"),
        ),
        body: Center(
          child: ChangeNotifierProvider<TimerModel>(
            builder: (context) => TimerModel(),
            child: Consumer<TimerModel>(builder: (context, timerModel, _) {
              return RaisedButton(
                onPressed: () async {
                  if (timerModel.count == 0) {
                    timerModel.startTimer();
                  }
                },

                child: Text(
                  timerModel.count == 0 ? "獲取驗證碼" : '${timerModel.count} 秒後重發',
                  style: timerModel.count == 0
                      ? TextStyle(color: Colors.blue, fontSize: 14)
                      : TextStyle(color: Colors.grey, fontSize: 14),
                ),
              );
            }),
          ),
        ),
      )
    );
  }
}

可以看到MyApp是繼承自 StatelessWidget的,是一個沒有狀態的widget。

通過在TimerModel中調用notifyListeners();實現刷新的效果。

2、StreamBuilder實現局部刷新

import 'package:flutter/material.dart';
import 'dart:async';
import 'package:rxdart/rxdart.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {

  final StreamController _streamController = StreamController<int>();

  int count = 10;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("短信倒計時"),
        ),
        body: Center(
          child: StreamBuilder<int>(
              stream: _streamController.stream,
              initialData: 0,
              builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
                return RaisedButton(
                  onPressed: () async {
                    if (snapshot.data == 0) {
                      startTimer();
                    }
                  },

                  child: Text(
                    snapshot.data == 0 ? "獲取驗證碼" : '${snapshot
                        .data} 秒後重發',
                    style: snapshot.data == 0
                        ? TextStyle(color: Colors.blue, fontSize: 14)
                        : TextStyle(color: Colors.grey, fontSize: 14),
                  ),
                );
              }
          ),
        ),
      )
    );
  }


  startTimer(){
    count = 10;
    Observable.periodic(Duration(seconds: 1))
        .take(10)
        .listen((t){
        _streamController.sink.add(--count);
    });
  }
}

使用StreamBuilder來局部刷新,通過sink.add方法向streamController.sink中添加一個事件流,這個流會被StreamBuilderstream接收,然後觸發builder方法。
最後在頁面銷燬的時候釋放資源。

效果圖

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章