Skip to content

Instantly share code, notes, and snippets.

@AlexV525
Last active October 29, 2023 17:51
Show Gist options
  • Save AlexV525/6067934cdcad26ab082010a926b58ad1 to your computer and use it in GitHub Desktop.
Save AlexV525/6067934cdcad26ab082010a926b58ad1 to your computer and use it in GitHub Desktop.
Lazy IndexedStack
@esDotDev
Copy link

esDotDev commented Apr 8, 2022

Thanks for the code! Here is an alternate version, that accounts for the child list size changing. It also doesn't accept a null index at all, which cleans up the code a little:

import 'package:flutter/material.dart';

/// A lazy-loading [IndexedStack] that loads [children] accordingly.
class LazyIndexedStack extends StatefulWidget {
  const LazyIndexedStack({
    Key? key,
    this.alignment = AlignmentDirectional.topStart,
    this.textDirection,
    this.sizing = StackFit.loose,
    this.index = 0,
    this.children = const [],
  }) : super(key: key);

  final AlignmentGeometry alignment;
  final TextDirection? textDirection;
  final StackFit sizing;
  final int index;
  final List<Widget> children;

  @override
  _LazyIndexedStackState createState() => _LazyIndexedStackState();
}

class _LazyIndexedStackState extends State<LazyIndexedStack> {
  late List<bool> _activated = _initializeActivatedList();

  List<bool> _initializeActivatedList() => List<bool>.generate(widget.children.length, (int i) => i == widget.index);

  @override
  void didUpdateWidget(covariant LazyIndexedStack oldWidget) {
    if (oldWidget.children.length != widget.children.length) {
      _activated = _initializeActivatedList();
    }
    super.didUpdateWidget(oldWidget);
  }

  @override
  Widget build(BuildContext context) {
    // Mark current index as active
    _activated[widget.index] = true;
    final children = List.generate(_activated.length, (i) {
      return _activated[i] ? widget.children[i] : const SizedBox.shrink();
    });
    return IndexedStack(
      alignment: widget.alignment,
      sizing: widget.sizing,
      textDirection: widget.textDirection,
      index: widget.index,
      children: children,
    );
  }
}

Other tweaks:

  • moved the buildChildren method inside of build, as its only 3 lines when using list.generate
  • Removed the check for _activatedList[widget.index] , looking it up is likely slower than just storing it

@AlexV525
Copy link
Author

Thanks for the code! Here is an alternate version, that accounts for the child list size changing. It also doesn't accept a null index at all, which cleans up the code a little

Hi @esDotDev. Thanks for the feedback!
I've setup a workshop with the implementation at https://github.com/AlexV525/dartpad_workshops/tree/main/implement_lazy_indexed_stack, and I guess I'll redirect the gist to the workshop recently. Can you review it and see if your updates are still working with the workshop version?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment