eq_indexd_stack 0.0.9
eq_indexd_stack: ^0.0.9 copied to clipboard
A high-performance lazy-loading IndexedStack for Flutter that initializes pages only when needed.
EQ Indexed Stack #
A high-performance lazy-loading IndexedStack implementation for Flutter that initializes pages only when they are needed. Perfect for bottom navigation, tab views, and any UI that requires switching between multiple views.
Features #
- ๐ Lazy Loading: Pages are only initialized when they're accessed, reducing memory usage and startup time
- โก Preloading: Optional preloading of specific pages during initialization
- ๐พ State Preservation: Configure which pages should maintain their state when not visible
- ๐งน Memory Efficiency: Configurable memory management that automatically disposes unused pages
- ๐ TickerMode Support: Automatically disables animations in inactive pages
- ๐ฎ Full Control: Explicit methods to preload or dispose specific pages
Installation #
Add this to your package's pubspec.yaml file:
dependencies:
eq_indexed_stack: ^0.0.81
Then run:
flutter pub get
Usage #
Basic Example #
import 'package:flutter/material.dart';
import 'package:eq_indexed_stack/eq_indexed_stack.dart';
class EQIndexedStackDemo extends StatefulWidget {
@override
_EQIndexedStackDemoState createState() => _EQIndexedStackDemoState();
}
class _EQIndexedStackDemoState extends State<EQIndexedStackDemo> {
late EQLazyStackController controller;
@override
void initState() {
super.initState();
// Initialize controller with options
controller = EQLazyStackController(
initialIndex: 0,
preloadIndexes: [1], // Preload second page
disposeUnused: true,
maxCachedPages: 3,
);
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('EQ Indexed Stack Demo')),
body: EQLazyLoadIndexedStack(
controller: controller,
children: [
HomePage(),
ProfilePage(),
SettingsPage(),
],
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: controller.currentIndex,
onTap: (index) => controller.switchTo(index, 3),
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Profile'),
BottomNavigationBarItem(icon: Icon(Icons.settings), label: 'Settings'),
],
),
);
}
}
Advanced Usage #
Multiple Stack Instances
You can use multiple EQLazyLoadIndexedStack instances with different controllers:
// Main navigation controller
final mainController = EQLazyStackController(
initialIndex: 0,
disposeUnused: true,
);
// Nested controller inside one of the main pages
final nestedController = EQLazyStackController(
initialIndex: 0,
maxCachedPages: 2,
);
// Use in widget tree
EQLazyLoadIndexedStack(
controller: mainController,
children: [
HomePage(),
EQLazyLoadIndexedStack(
controller: nestedController,
children: [
SubPage1(),
SubPage2(),
],
),
SettingsPage(),
],
);
Force Cleanup
You can manually manage page disposal:
// Reset controller to clean up all pages except the current one and preloaded pages
controller.reset();
// Dispose a specific page
controller.disposePage(2);
// Dispose multiple pages at once
controller.disposePages([1, 3, 4]);
// Switch pages with possible automatic cleanup (if disposeUnused is true)
controller.switchTo(newIndex, totalPages);
Debugging Memory Usage
Track which pages are kept in memory:
// Check if a specific page is loaded
bool isPageLoaded = controller.isLoaded(2);
// Get all currently loaded page indexes
Set<int> loadedPages = controller.loadedIndexes;
How It Works #
Under the hood, eq_indexed_stack uses a combination of optimized techniques:
- Efficient State Management: Only loaded pages are included in the render tree
- Offstage + TickerMode: Hidden pages use Offstage and TickerMode to minimize resource usage
- Smart Page Management: Automatically tracks and manages page history for optimal memory cleanup
- Direct Listenable Implementation: Uses minimal overhead for reactivity
This creates a high-performance stack that:
- Reduces initial load time
- Minimizes memory consumption
- Improves overall app responsiveness
- Maintains state only where needed
Performance Tips #
To get the best performance:
- Set appropriate
maxCachedPagesbased on your app's memory constraints - Enable
disposeUnusedfor apps with many heavy pages - Use
preloadIndexesfor pages that users are likely to visit immediately - Call
reset()when navigation patterns change significantly - Use
disposePage()ordisposePages()for explicit memory management
Complete API #
EQLazyStackController #
EQLazyStackController({
int initialIndex = 0, // Starting page index
List<int> preloadIndexes = [], // Pages to preload on initialization
bool disposeUnused = false, // Whether to dispose pages exceeding maxCachedPages
int maxCachedPages = 3, // Maximum number of pages to keep in memory
})
Properties:
currentIndex: Current visible page indexloadedIndexes: Set of indexes that are currently loadedisLoaded(int index): Check if a page is loaded
Methods:
switchTo(int index, int totalPages): Switch to a specific pagedisposePage(int index): Dispose a specific pagedisposePages(List<int> indexes): Dispose multiple specific pagesreset(): Reset controller state, clearing all pages except current and preloadeddispose(): Dispose controller resources
EQLazyLoadIndexedStack #
EQLazyLoadIndexedStack({
required EQLazyStackController controller, // Controller for the stack
required List<Widget> children, // Pages to display
AlignmentGeometry alignment = AlignmentDirectional.topStart, // Alignment
StackFit sizing = StackFit.loose, // How to size children
TextDirection? textDirection, // Text direction for alignment
})
License #
MIT
Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.