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

`Loupe` Flutter compatible widget for integration with the non invasive `loupe` reactive library

Loupe Flutter #

A Flutter widget integration for the loupe reactive state management library.

Loupe Flutter provides a Loupe widget that automatically rebuilds when watched objects change, making it easy to integrate loupe's reactive system with Flutter's declarative UI.

Features #

  • Automatic rebuilds - Widget rebuilds when any watched object changes
  • Simple API - Just provide a build function and a list of objects to watch
  • Memory safe - Automatically unsubscribes when widget is disposed
  • Lightweight - Minimal overhead, built on top of the zero-dependency loupe package

Installation #

Add to your pubspec.yaml:

dependencies:
  loupe_flutter:
    git:
      url: https://github.com/your-repo/loupe_flutter.git
      ref: main
  loupe:
    git:
      url: https://github.com/your-repo/loupe.git
      ref: main

Or if published to pub.dev:

dependencies:
  loupe_flutter: ^1.0.0
  loupe: ^1.0.0

Usage #

Basic Usage #

import 'package:flutter/material.dart';
import 'package:loupe/loupe.dart';
import 'package:loupe_flutter/loupe_flutter.dart';

class Counter {
  int _count = 0;
  int get count => _count;

  void increment() {
    _count++;
    notifyChanges(this);
  }
}

class MyApp extends StatelessWidget {
  final counter = Counter();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Loupe(
            watchList: [counter],
            build: (context) => Text('Count: ${counter.count}'),
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: counter.increment,
          child: const Icon(Icons.add),
        ),
      ),
    );
  }
}

Watching Multiple Objects #

class UserProfile {
  String name;
  int age;
  UserProfile(this.name, this.age);

  void updateName(String newName) {
    name = newName;
    notifyChanges(this);
  }

  void updateAge(int newAge) {
    age = newAge;
    notifyChanges(this);
  }
}

class Settings {
  String theme = 'light';
  
  void toggleTheme() {
    theme = theme == 'light' ? 'dark' : 'light';
    notifyChanges(this);
  }
}

Loupe(
  watchList: [userProfile, settings],
  build: (context) => Column(
    children: [
      Text('Name: ${userProfile.name}'),
      Text('Age: ${userProfile.age}'),
      Text('Theme: ${settings.theme}'),
    ],
  ),
)

Nested Loupe Widgets #

Loupe(
  watchList: [user],
  build: (context) => Column(
    children: [
      Text('User: ${user.name}'),
      Loupe(
        watchList: [user.settings],
        build: (context) => Text('Settings: ${user.settings.theme}'),
      ),
    ],
  ),
)

API Reference #

Loupe Widget #

A StatefulWidget that rebuilds when watched objects change.

Constructor:

Loupe({
  Key? key,
  required Widget Function(BuildContext) build,
  required List<Object> watchList,
})

Parameters:

  • key - Optional widget key
  • build - A function that builds the widget tree. Called on every rebuild.
  • watchList - A list of objects to watch for changes. When notifyChanges() is called on any of these objects, the widget rebuilds.

Important Notes #

  • Object Identity: Like the underlying loupe package, this widget uses object identity to track changes. Primitive types (int, String, bool, etc.) will not work correctly. Always use reference types (class instances).
  • Manual Notification: You must call notifyChanges(obj) explicitly when an object changes. The widget does not automatically detect changes.
  • Automatic Cleanup: The widget automatically unsubscribes from all watched objects when it is disposed, preventing memory leaks.
  • BuildContext: The build callback receives the current BuildContext, just like any other Flutter widget builder.

Comparison with Other State Management Solutions #

Feature Loupe Flutter Provider Riverpod Bloc
Dependencies Minimal Flutter Many Many
Learning Curve Low Low Medium High
Boilerplate Minimal Minimal Minimal High
Testability Easy Easy Easy Medium
Reactivity Manual Automatic Automatic Manual

Loupe Flutter is ideal when you want:

  • A simple, explicit reactive system
  • Minimal dependencies
  • Full control over when notifications happen
  • Easy integration with existing code

Example: Complete Counter App #

import 'package:flutter/material.dart';
import 'package:loupe/loupe.dart';
import 'package:loupe_flutter/loupe_flutter.dart';

class Counter {
  int _count = 0;
  int get count => _count;

  void increment() {
    _count++;
    notifyChanges(this);
  }

  void decrement() {
    _count--;
    notifyChanges(this);
  }

  void reset() {
    _count = 0;
    notifyChanges(this);
  }
}

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Loupe Counter',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const CounterPage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    final counter = Counter();

    return Scaffold(
      appBar: AppBar(title: const Text('Loupe Counter')),
      body: Center(
        child: Loupe(
          watchList: [counter],
          build: (context) => Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text('You have pushed the button this many times:'),
              Text(
                '${counter.count}',
                style: Theme.of(context).textTheme.headlineMedium,
              ),
              const SizedBox(height: 20),
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  FloatingActionButton(
                    onPressed: counter.decrement,
                    tooltip: 'Decrement',
                    child: const Icon(Icons.remove),
                  ),
                  const SizedBox(width: 20),
                  FloatingActionButton(
                    onPressed: counter.reset,
                    tooltip: 'Reset',
                    child: const Icon(Icons.exposure_zero),
                  ),
                  const SizedBox(width: 20),
                  FloatingActionButton(
                    onPressed: counter.increment,
                    tooltip: 'Increment',
                    child: const Icon(Icons.add),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

License #

MIT License.

0
likes
140
points
97
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

`Loupe` Flutter compatible widget for integration with the non invasive `loupe` reactive library

Repository

License

BSD-3-Clause (license)

Dependencies

flutter, loupe

More

Packages that depend on loupe_flutter