raii 0.2.0 copy "raii: ^0.2.0" to clipboard
raii: ^0.2.0 copied to clipboard

Resource Acquisition Is Initialization (RAII) pattern for Dart, providing automated lifecycle management of resources.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:raii/flutter.dart';
import 'package:raii/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'RAII Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const RaiiHomePage(),
    );
  }
}

class RaiiHomePage extends StatefulWidget {
  const RaiiHomePage({super.key});

  @override
  State<RaiiHomePage> createState() => _RaiiHomePageState();
}

class _RaiiHomePageState extends State<RaiiHomePage>
    with TickerProviderStateMixin, RaiiStateMixin {
  // Controllers with automatic lifecycle management
  late final tabController = TabController(length: 3, vsync: this)
      .withLifecycle(this, debugLabel: 'Tabs');

  late final scrollController =
      ScrollController().withLifecycle(this, debugLabel: 'Scroll');

  late final textController =
      TextEditingController().withLifecycle(this, debugLabel: 'TextInput');

  late final focusNode =
      FocusNode().withLifecycle(this, debugLabel: 'FocusNode');

  late final animationController = AnimationController(
    vsync: this,
    duration: const Duration(milliseconds: 300),
  ).withLifecycle(
    this,
    debugLabel: 'Animation',
  );

  late final animation = CurvedAnimation(
    parent: animationController,
    curve: Curves.easeInOut,
  );

  @override
  void initLifecycle() {
    super.initLifecycle();

    // Register app lifecycle observer
    WidgetsBinding.instance.addObserverWithLifeycle(
      this,
      AppLifecycleObserver(onResume: _handleAppResume),
      debugLabel: 'AppLifecycle',
    );

    // Listen to tab changes
    tabController.addListenerWithLifecycle(
      this,
      _handleTabChange,
      debugLabel: 'TabListener',
    );

    // Listen to scroll updates
    scrollController.addListenerWithLifecycle(
      this,
      _handleScroll,
      debugLabel: 'ScrollListener',
    );

    // Listen to text changes
    textController.addListenerWithLifecycle(
      this,
      _handleTextChange,
      debugLabel: 'TextListener',
    );

    // Listen to focus changes
    focusNode.addListenerWithLifecycle(
      this,
      _handleFocusChange,
      debugLabel: 'FocusListener',
    );

    // Listen to animation updates
    animation.addListenerWithLifecycle(
      this,
      _handleAnimationUpdate,
      debugLabel: 'AnimationListener',
    );
  }

  void _handleAppResume() {
    debugPrint('App resumed - restoring state');
  }

  void _handleTabChange() {
    debugPrint('Tab changed: ${tabController.index}');
  }

  void _handleScroll() {
    debugPrint('Scroll position: ${scrollController.offset}');
  }

  void _handleTextChange() {
    debugPrint('Text changed: ${textController.text}');
  }

  void _handleFocusChange() {
    debugPrint('Focus changed: ${focusNode.hasFocus}');
  }

  void _handleAnimationUpdate() {
    debugPrint('Animation value: ${animation.value}');
    setState(() {});
  }

  void _toggleAnimation() {
    if (animationController.status == AnimationStatus.completed) {
      animationController.reverse();
    } else {
      animationController.forward();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('RAII Example'),
        bottom: TabBar(
          controller: tabController,
          tabs: const [
            Tab(icon: Icon(Icons.home), text: 'Home'),
            Tab(icon: Icon(Icons.list), text: 'List'),
            Tab(icon: Icon(Icons.settings), text: 'Settings'),
          ],
        ),
      ),
      body: TabBarView(
        controller: tabController,
        children: [
          // Home tab
          Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 24),
                  child: TextField(
                    controller: textController,
                    focusNode: focusNode,
                    decoration: const InputDecoration(
                      labelText: 'Type something',
                      border: OutlineInputBorder(),
                    ),
                  ),
                ),
                const SizedBox(height: 20),
                AnimatedBuilder(
                  animation: animation,
                  builder: (context, child) => Transform.scale(
                    scale: 1.0 + animation.value * 0.5,
                    child: ElevatedButton(
                      onPressed: _toggleAnimation,
                      child: const Text('Animate Me'),
                    ),
                  ),
                ),
              ],
            ),
          ),
          // List tab
          ListView.builder(
            controller: scrollController,
            itemCount: 100,
            itemBuilder: (context, index) => ListTile(
              title: Text('Item $index'),
            ),
          ),
          // Settings tab
          const Center(
            child: Text('Settings Content'),
          ),
        ],
      ),
    );
  }
}

class AppLifecycleObserver with WidgetsBindingObserver {
  final VoidCallback onResume;

  AppLifecycleObserver({required this.onResume});

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    switch (state) {
      case AppLifecycleState.resumed:
        debugPrint('App resumed');
        onResume();
        break;
      case AppLifecycleState.inactive:
        debugPrint('App inactive');
        break;
      case AppLifecycleState.paused:
        debugPrint('App paused - saving state');
        break;
      case AppLifecycleState.detached:
        debugPrint('App detached');
        break;
      case AppLifecycleState.hidden:
        debugPrint('App hidden');
        break;
    }
  }

  @override
  void didChangePlatformBrightness() {
    debugPrint('Brightness changed');
  }
}
11
likes
160
points
36
downloads

Publisher

verified publisherandrei.kabylin.dev

Weekly Downloads

Resource Acquisition Is Initialization (RAII) pattern for Dart, providing automated lifecycle management of resources.

Repository (GitHub)
View/report issues

Topics

#raii #lifecycle #resource-management #state-management

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on raii