Home > Back-end >  How `double dot` or `cascade notation` works when adding to list?
How `double dot` or `cascade notation` works when adding to list?

Time:10-02

I have trouble understanding the bellow section of the code in this LINK

I read THIS article about Cascade notation but no result. I can debug the code but things don't go as I expect.

     // Does this line should empty the list? but it doesn't?
_items = []         
    // This line adds a value in *Counter* to list and create a new object as a return?
..add(counter  )   
   // How list _items will be added to _items again? This part is really confusing to me
..addAll(_items);   

Complete Code:


    import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(primarySwatch: Colors.blue, brightness: Brightness.dark),
      home: SimpleAnimatedList(),
    );
  }
}

class SimpleAnimatedList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SliceAnimatedList(),
    );
  }
}

class SliceAnimatedList extends StatefulWidget {
  @override
  _SliceAnimatedListState createState() => _SliceAnimatedListState();
}

class _SliceAnimatedListState extends State<SliceAnimatedList> {
  final GlobalKey<AnimatedListState> listKey = GlobalKey<AnimatedListState>();
  List<int> _items = [];
  int counter = 0;

  Widget slideIt(BuildContext context, int index, animation) {
    int item = _items[index];
    TextStyle? textStyle = Theme.of(context).textTheme.headline4;
    return SlideTransition(
      position: Tween<Offset>(
        begin: const Offset(-1, 0),
        end: Offset(0, 0),
      ).animate(animation),
      child: SizedBox(
        height: 128.0,
        child: Card(
          color: Colors.primaries[item % Colors.primaries.length],
          child: Center(child: Text('Item $item', style: textStyle)),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.max,
      children: <Widget>[
        Expanded(
          child: Container(
            height: double.infinity,
            child: AnimatedList(
              key: listKey,
              initialItemCount: _items.length,
              itemBuilder: (context, index, animation) {
                return slideIt(context, index, animation);
              },
            ),
          ),
        ),
        Container(
          decoration: BoxDecoration(color: Colors.greenAccent),
          child: Row(
            mainAxisSize: MainAxisSize.max,
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              TextButton(
                onPressed: () {
                  setState(() {
                    listKey.currentState?.insertItem(0,
                        duration: const Duration(milliseconds: 500));
                   //////////////////////////////////////////////
                    _items = []
                      ..add(counter  )
                      ..addAll(_items);
                  /////////////////////////////////////////////
                  });
                },
                child: Text(
                  "Add item to first",
                  style: TextStyle(color: Colors.black, fontSize: 20),
                ),
              ),
              TextButton(
                onPressed: () {
                  if (_items.length <= 1) return;
                  listKey.currentState?.removeItem(
                      0, (_, animation) => slideIt(context, 0, animation),
                      duration: const Duration(milliseconds: 500));
                  setState(() {
                    _items.removeAt(0);
                  });
                },
                child: Text(
                  "Remove first item",
                  style: TextStyle(color: Colors.black, fontSize: 20),
                ),
              )
            ],
          ),
        ),
      ],
    );
  }
}


CodePudding user response:

In simple words, the cascading operator, that is "..", passes the result of the previous operation directly to the next operation.

For example:

var list=[]
..add(value)
..add(value2);

This statement first initialize empty list then add value to the list. After adding value it adds value2 to the list.

So this is generally the short form of:

var list=[];
list.add(value);
list.add(value2);

Here is the definition.

CodePudding user response:

The Cascade notation is just for writing less code. Instead of writing the below code where you need to write _items variable every time you want to access the methods (add, addAll, etc), you can do it just by writing the cascade notation. The code looks much cleaner and fluid code.

_items = [];
_items.add(counter  );
_items.addAll(_items);

Hope this will clear things up for you. Happy coding!

CodePudding user response:

Interesting use-case.

I can decode the code for you, Along with cascading, scoping is also being used.

_items = []         
..add(counter  )   
..addAll(_items);

You can break this in following part

  1. _items is a list hence it points to some memory address (lets say 0x1000 for simplicity)
  2. You create a new list with []. Let's say it points to some other memory address (0x1500).
  3. Cascading operation means that an operation 'op' can be performed on an object but instead of returning of Type which is defined for 'op' (for example bool add(int t)), same object is returned on which cascading was performed. Here 'object' is returned instead of bool.
  4. When ..add(counter ) is done, List object pointing to memory address (0x1500) is returned and the list which was empty earlier contains single item.
  5. When ..addAll(_items) is performed, you are telling to add all the items from list at address (0x1000) to be added to list object which was returned earlier (i.e. list at 0x1500). So all items are added.
  6. One the operation is done, Right side of = operator is evaluated and list pointing to memory address 0x1500 is retuned which is assigned to variable written at left side (which is _items).

TL;DR: The all three lines are actually one statement.

I hope I cleared your doubt.

  • Related