aero_mvvm 0.0.1 copy "aero_mvvm: ^0.0.1" to clipboard
aero_mvvm: ^0.0.1 copied to clipboard

A zero-dependency, highly performant MVVM state management framework for Flutter. Provides context-less routing, async state handling, and granular reactive UI rebuilds.

example/lib/main.dart

// ignore_for_file: depend_on_referenced_packages
import 'package:flutter/material.dart';
import 'package:aero_mvvm/aero_mvvm.dart';

// =============================================================================
// 1. GLOBAL STATE (Simulated App-Wide State)
// =============================================================================

class CartViewModel extends ViewModel {
  int itemCount = 0;
  double totalPrice = 0.0;

  void addToCart(double price) {
    itemCount++;
    totalPrice += price;
    rebuild();
  }
}

final globalCart = CartViewModel();

// =============================================================================
// 2. LOCAL ASYNC STATE (Screen-Specific Logic)
// =============================================================================

class ProductViewModel extends AsyncViewModel {
  String selectedColor = "Matte Black";
  double productPrice = 299.99;
  String productTitle = "AeroSonic Pro ANC";

  final List<String> availableColors = [
    "Matte Black",
    "Lunar Silver",
    "Navy Blue",
  ];

  void changeColor(String color) {
    selectedColor = color;
    rebuild();
  }

  void fetchProductDetails() {
    runAsync(() async {
      await Future.delayed(const Duration(seconds: 2));
      // Data is now "loaded"
    });
  }
}

// =============================================================================
// 3. THE APPLICATION
// =============================================================================

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Aero MVVM Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.black,
          brightness: Brightness.dark,
        ),
        useMaterial3: true,
      ),
      home: const ProductScreen(),
    );
  }
}

// =============================================================================
// 4. THE UI (Pure layout, zero business logic)
// =============================================================================

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

  @override
  Widget build(BuildContext context) {
    return ViewModelBuilder<ProductViewModel>(
      viewModelBuilder: () => ProductViewModel(),

      onModelReady: (viewModel) => viewModel.fetchProductDetails(),
      builder: (context, productViewModel) {
        return Scaffold(
          backgroundColor: const Color(0xFF121212),
          appBar: AppBar(
            backgroundColor: Colors.transparent,
            elevation: 0,
            title: const Text(
              'Aero Store',
              style: TextStyle(fontWeight: FontWeight.bold),
            ),
            actions: [
              // ---------------------------------------------------------------
              // DEMO: ViewModelBuilder listening to GLOBAL state
              // ---------------------------------------------------------------
              ViewModelBuilder<CartViewModel>(
                viewModelBuilder: () => globalCart,
                builder: (context, cart) {
                  return Padding(
                    padding: const EdgeInsets.only(right: 20.0),
                    child: Center(
                      child: Badge(
                        isLabelVisible: cart.itemCount > 0,
                        label: Text('${cart.itemCount}'),
                        child: const Icon(Icons.shopping_bag_outlined),
                      ),
                    ),
                  );
                },
              ),
            ],
          ),

          // -------------------------------------------------------------------
          // DEMO: AsyncViewModel handling loading states automatically
          // -------------------------------------------------------------------
          body: productViewModel.isBusy
              ? const Center(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      CircularProgressIndicator(color: Colors.white),
                      SizedBox(height: 16),
                      Text(
                        "Fetching premium products...",
                        style: TextStyle(color: Colors.grey),
                      ),
                    ],
                  ),
                )
              : _buildProductDetails(productViewModel),

          // -------------------------------------------------------------------
          // DEMO: MultiViewModelBuilder merging global AND local state
          // -------------------------------------------------------------------
          bottomNavigationBar: MultiViewModelBuilder(
            viewModels: [globalCart, productViewModel],
            builder: (context) {
              return Container(
                padding: const EdgeInsets.all(24.0),
                decoration: BoxDecoration(
                  color: const Color(0xFF1E1E1E),
                  borderRadius: const BorderRadius.vertical(
                    top: Radius.circular(30),
                  ),
                  boxShadow: [BoxShadow(color: Colors.black.withValues(alpha: 0.5), blurRadius: 20)],
                ),
                child: SafeArea(
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Column(
                        mainAxisSize: MainAxisSize.min,
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          const Text(
                            "Total Cart",
                            style: TextStyle(color: Colors.grey),
                          ),
                          Text(
                            "\$${globalCart.totalPrice.toStringAsFixed(2)}",
                            style: const TextStyle(
                              fontSize: 24,
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                        ],
                      ),
                      ElevatedButton(
                        style: ElevatedButton.styleFrom(
                          backgroundColor: Colors.white,
                          foregroundColor: Colors.black,
                          padding: const EdgeInsets.symmetric(
                            horizontal: 32,
                            vertical: 16,
                          ),
                          shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(16),
                          ),
                        ),
                        // Add the item to the global cart when clicked!
                        onPressed: () =>
                            globalCart.addToCart(productViewModel.productPrice),
                        child: Text("Add ${productViewModel.selectedColor}"),
                      ),
                    ],
                  ),
                ),
              );
            },
          ),
        );
      },
    );
  }

  // A helper method to keep the main build method clean
  Widget _buildProductDetails(ProductViewModel viewModel) {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(24.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // Simulated Product Image Area
          Container(
            height: 300,
            width: double.infinity,
            decoration: BoxDecoration(
              gradient: const LinearGradient(
                colors: [Color(0xFF2A2A2A), Color(0xFF1A1A1A)],
                begin: Alignment.topLeft,
                end: Alignment.bottomRight,
              ),
              borderRadius: BorderRadius.circular(30),
            ),
            child: const Icon(
              Icons.headphones,
              size: 120,
              color: Colors.white24,
            ),
          ),
          const SizedBox(height: 32),

          Text(
            viewModel.productTitle,
            style: const TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
          ),
          const SizedBox(height: 8),
          Text(
            "\$${viewModel.productPrice}",
            style: const TextStyle(fontSize: 24, color: Colors.grey),
          ),

          const SizedBox(height: 32),
          const Text(
            "Select Color",
            style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
          ),
          const SizedBox(height: 16),

          // Color Selector Chips
          Wrap(
            spacing: 12,
            children: viewModel.availableColors.map((color) {
              final isSelected = viewModel.selectedColor == color;
              return ChoiceChip(
                label: Text(color),
                selected: isSelected,
                onSelected: (_) => viewModel.changeColor(color),
                selectedColor: Colors.white,
                labelStyle: TextStyle(
                  color: isSelected ? Colors.black : Colors.white,
                  fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
                ),
                backgroundColor: const Color(0xFF2A2A2A),
              );
            }).toList(),
          ),
        ],
      ),
    );
  }
}
0
likes
150
points
26
downloads

Documentation

API reference

Publisher

verified publishermocknode.dev

Weekly Downloads

A zero-dependency, highly performant MVVM state management framework for Flutter. Provides context-less routing, async state handling, and granular reactive UI rebuilds.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter

More

Packages that depend on aero_mvvm