【无标题】

文章目录

  • 1. 概念介绍
  • 2. 方法与原理
    • 2.1 实现方法
    • 2.2 实现原理

我们在上一章回中介绍了"再谈showMenu的用法",本章回中将介绍如何实现每隔一段时间执行某项任务.闲话休提,让我们一起Talk Flutter吧。

【无标题】_第1张图片

1. 概念介绍

在实际项目中会有定时执行任务的需求,比如每隔1秒去发送网络心跳包,对于这样的需求,可以通过Stream.periodic(Duration,(){}).take(times)来实现,
再配合StreamProvider或者StreamBuilder就可以监听Stream中的事件。本章回中将介绍详细的使用方法。

2. 方法与原理

2.1 实现方法

介绍完概念后,我们看看如何实现这个概念,下面是具体的实现方法:

  • 创建一个Stream,并且调用它的priodic方法来执行定期任务;
  • 创建一个StreamBuilder,用来监听Stream中的事件;
  • 通过StreamBuilder中的buidler属性获取Stream中的事件;
  • 获取事件后,可以依据事件中的数据实现相关的逻辑业务处理;

2.2 实现原理

上面的实现方法中使用StreamBuilder来监听Stream中的事件,这个容易理解,我们重点看看Stream是如何实现每隔一段时间执行某项任务的,下面是它的源代码:

 factory Stream.periodic(Duration period,
      [T computation(int computationCount)?]) {
    if (computation == null && !typeAcceptsNull<T>()) {
      throw ArgumentError.value(null, "computation",
          "Must not be omitted when the event type is non-nullable");
    }
    var controller = _SyncStreamController<T>(null, null, null, null);
    // Counts the time that the Stream was running (and not paused).
    Stopwatch watch = new Stopwatch();
    controller.onListen = () {
      int computationCount = 0;
      void sendEvent(_) {
        watch.reset();
        if (computation != null) {
          T event;
          try {
            event = computation(computationCount++);
          } catch (e, s) {
            controller.addError(e, s);
            return;
          }
          controller.add(event);
        } else {
          controller.add(null as T); // We have checked that null is T.
        }
      }

      Timer timer = Timer.periodic(period, sendEvent);
      controller
        ..onCancel = () {
          timer.cancel();
          return Future._nullFuture;
        }
        ..onPause = () {
          watch.stop();
          timer.cancel();
        }
        ..onResume = () {
          Duration elapsed = watch.elapsed;
          watch.start();
          timer = new Timer(period - elapsed, () {
            timer = Timer.periodic(period, sendEvent);
            sendEvent(null);
          });
        };
    };
    return controller.stream;
  }

从上面的源代码中可以看到,该代码主要通过Timer来实现定期执行某项任务,不过它也有一些局限性,因为event的值递增的(computation(computationCount++))。如果使用StreamProvider指定初始值,但是它还会回到原来的默认值,比如指定泛型为int,初始值为3,它开始运行时值为3,指定时间到了后又变成了默认值0.此后
这个值进行递增,直到执行times次后停止。

///自己实现的计时器,和Stream.periodic()方法的原理相同,不同之处在于可以控制事件的逻辑,Stream中只能是做加法
TextButton(
  onPressed: () {
    Timer.periodic(const Duration(seconds: 1,), (timer) {
      setState(() {
        countdownTime++;
        if(countdownTime == 5) {
          timer.cancel();
        }
      });
    });
  },
  child: countdownTime == 0 ? const Text("Start") : Text(countdownTime.toString()),
),
///模拟上一个内容,做成倒计时,不过需要先启动上一个按钮,加到5以后才能启动下一个按钮
TextButton(
  onPressed: () {
    Timer.periodic(const Duration(seconds: 1,), (timer) {
      setState(() {
        countdownTime--;
        if(countdownTime == 0) {
          timer.cancel();
        }
      });
    });
  },
  child: countdownTime != 0 ? const Text("Start") : Text(countdownTime.toString()),
),

你可能感兴趣的:(一起Talk,Flutter吧,移动开发Flutter)