Photograph via Wilhelm Gunkel on Unsplash


On this article, we will be able to describe how we will reach a complicated type-writer effect:

Typewriter effect
Creator: DEV Neighborhood

Even though there are some programs to be had on, like the only described on this article, the standard query is: “do we really need another package in our beloved pubspeck just for this..?” Let’s discover some options like:

after which we will be able to see!


Generator purposes in Dart are used to supply a chain of values, sequentially, separately.

The values equipped via a generator object aren’t “cooked” before-hand: in truth, those values are created lazily, on call for.

In Dart, you’ll be able to create 2 varieties of turbines:

  • Synchronous generator: it blocks the execution till the series is equipped.
  • Asynchronous generator: supplies the series similtaneously, whilst acting different duties at (nearly) the similar time.

Even though they’re applied otherwise, each varieties have some options in not unusual:

  • they’re marked with * earlier than the frame of the serve as, as a way to state they’re “generator” strategies
  • the key phrase “yield” is used as a way to give you the present worth generated via the series

Synchronous generator

Synchronous generator purposes are marked with sync* earlier than their frame. Returned knowledge sort within the serve as signature will have to be a Iterable<T>, the place T is the generic knowledge sort for the article contained within the sequence. So we will have, for example:

Iterable<String> generateNames() sync* {

Iterable<int> generateNums() sync* {

However, within the serve as frame, those strategies don’t explicitly go back any worth. As a substitute, they “provide” some component the use of the yield commentary.

The next code display a synchronous generator that gives a suite of numbers:

Iterable<int> generateNumsSync() sync* {
  var i = 0;
  whilst (i < 10) {
    yield i++;//XXX: use yield to "push" the present worth...

Asynchronous generator

Alternatively, asynchronous generator purposes use the async* modifier and go back a Circulate<T> as a substitute. So:

Circulate<int> generateNumsAsync() async* {
  var i = 0;
  whilst (i < 10) {
    //XXX: right here shall we look ahead to a while...    
    yield i++;

As proven on the former snippet, asynchronous turbines don’t go back a price explicitly both.

Yet one more factor: in the event you ever wish to create a recursive generator, then you’ll be able to use the modifier yield*.

Now we’ve noticed the construction of turbines, let’s see how we will “hook” their effects into the widget tree.


The StreamBuilder widget listens for occasions on a given move and updates its kid each time a brand new merchandise is equipped down the move. So you’ll be able to consider it as some form of implementation of the observer development.

This widget builds its kid the use of the builder development. A few of the parameters gained, it will get a “picture” of the present state of the move thru an AsyncSnapshot object:

   move: ...,
   builder: (BuildContext context, AsyncSnapshot<int> snapshot) {

This snapshot object incorporates the object emitted via the move, but additionally different data, such because the state of the relationship between the widget and the move, any error that can have took place… Happily for us, this weblog is an bug-free atmosphere 🙂 but if operating on manufacturing apps, we must take a look at all this extra data earlier than gaining access to the move.

The type-writer text

Now that we know the way turbines and streambuilders paintings, we will use either one of them for our type-writer effect! So let’s put the entire shifting items in combination:

  • the text we wish to animate will also be encapsulated on a type magnificence, so one in all its strategies supply us with a move of values:
magnificence StreamableTextModel {
  ultimate String msg;

  const StreamableTextModel({this.msg = ""}) : assert(msg != null);

  Circulate<String> toStream() async* {
    for (var i = 0; i < msg.duration; i++) {
      yield msg.substring(0, i + 1);
  • execution will also be “paused” between emissions the use of Future.delayed()
  • a streambuilder widget can be utilized to hear the former move and replace the UI accordingly
 Widget construct(BuildContext context) {
    go back StreamBuilder<String>(
        initialData: "",
        move: ...,
        builder: (BuildContext cntxt, AsyncSnapshot<String> snap) {
          if (snap.hasData) {
            go back Text(snap.knowledge);
          } else {
            go back Text("");

And that will be the end result (you higher skip the preliminary clean seconds…):


Via combining turbines and streambuilders, we will construct dynamic widgets which can be up to date robotically when some knowledge adjustments. This let us create “fake” animations like the only we described.

Write you subsequent time! As same old, complete supply code is to be had at:


Please enter your comment!
Please enter your name here