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方法。
最后在页面销毁的时候释放资源。

效果图

在这里插入图片描述

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值