lindi 0.1.1 copy "lindi: ^0.1.1" to clipboard
lindi: ^0.1.1 copied to clipboard

Lindi is a lightweight and reactive state management library for Flutter that simplifies building applications with dynamic UI updates.

Lindi #

Lindi is a lightweight and reactive state management library for Flutter that simplifies building applications with dynamic UI updates. It enables developers to manage state using LindiViewModel and provides powerful widgets like LindiBuilder and LindiMultiBuilder to listen and react to changes in state.

Features #

  • Easy state management with LindiViewModel.
  • Reactivity using LindiBuilder for single state.
  • Combine multiple state objects with LindiMultiBuilder.
  • Global dependency injection with LindiInjector.
  • Lightweight, intuitive, and easy to integrate.

Installation #

pub package

Add Lindi to your Flutter project by including it in your pubspec.yaml:

dependencies:
  lindi: latest_version
copied to clipboard

Then run:

flutter pub get
copied to clipboard

Getting Started #

1. Define a LindiViewModel #

Create a class that extends LindiViewModel to manage your state:

class CounterLindiViewModel extends LindiViewModel {
  int counter = 0;

  void increment() {
    counter++;
    notify();
  }

  void decrement() {
    counter--;
    notify();
  }
}
copied to clipboard

Create a class that extends LindiViewModel<D, E> to manage your state:

class ApiLindiViewModel extends LindiViewModel<String, String> {
  
  void fetchData() async {
    setLoading();
    await Future.delayed(Duration(seconds: 4));
    setData('Fetched');
    await Future.delayed(Duration(seconds: 3));
    setError('Timeout!');
  }
}
copied to clipboard
  • ApiLindiViewModel inherits from LindiViewModel<String, String>, where:
    • <D> represents the data type (in this case, API response data as String).
    • <E> represents the error type (in this case, error as String).

2. Register Your LindiViewModel #

Use LindiInjector to make the LindiViewModel accessible globally:

void main() {
  LindiInjector.register(CounterLindiViewModel());
  LindiInjector.register(ApiLindiViewModel()..fetchData());
  runApp(const MyApp());
}
copied to clipboard

3. Use LindiBuilder #

React to changes in a single LindiViewModel with LindiBuilder:

class CounterScreen extends StatelessWidget {
  @override 
  Widget build(BuildContext context) {
    final counterViewModel = LindiInjector.get<CounterLindiViewModel>();

    return Scaffold(
      body: Center(
        child: LindiBuilder(
          viewModel: counterViewModel,
          builder: (context) {
            return Text(
              'Counter: ${counterViewModel.counter}',
              style: const TextStyle(fontSize: 24),
            );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: counterViewModel.increment,
        child: const Icon(Icons.add),
      ),
    );
  }
}
copied to clipboard

React to changes in a single LindiViewModel<D, E> with LindiBuilder:

class ApiScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final apiViewModel = LindiInjector.get<ApiLindiViewModel>();

    return Scaffold(
      body: Center(
        child: LindiBuilder(
          viewModel: apiViewModel,
          builder: (context) {
            if(apiViewModel.isLoading){
              return CircularProgressIndicator();
            }
            if(apiViewModel.hasError){
              return Text(apiViewModel.error!);
            }
            return Text(apiViewModel.data!);
          },
        ),
      ),
    );
  }
}
copied to clipboard

4. Use LindiMultiBuilder #

Listen to multiple LindiViewModel instances simultaneously:

class ThemeLindiViewModel extends LindiViewModel {
  bool isDarkMode = false;

  void toggleTheme() {
    isDarkMode = !isDarkMode;
    notify();
  }
}

class MultiExampleScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counterViewModel = LindiInjector.get<CounterLindiViewModel>();
    final themeViewModel = LindiInjector.get<ThemeLindiViewModel>();

    return Scaffold(
      body: LindiMultiBuilder(
        viewModels: [counterViewModel, themeViewModel],
        builder: (context) {
          return Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(
                  'Counter: ${counterViewModel.counter}',
                  style: const TextStyle(fontSize: 24),
                ),
                const SizedBox(height: 20),
                ElevatedButton(
                  onPressed: counterViewModel.increment,
                  child: const Text('Increment Counter'),
                ),
                const SizedBox(height: 40),
                Text(
                  'Current Theme: ${themeViewModel.isDarkMode ? "Dark" : "Light"}',
                  style: const TextStyle(fontSize: 18),
                ),
                const SizedBox(height: 20),
                IconButton(
                  icon: Icon(
                    themeViewModel.isDarkMode ? Icons.dark_mode : Icons.light_mode,
                  ),
                  onPressed: themeViewModel.toggleTheme,
                ),
              ],
            ),
          );
        },
      ),
    );
  }
}
copied to clipboard

API Reference #

LindiViewModel #

  • Extend this class to define your state management logic.
  • Call notify() to update listeners when state changes.
  • Call setLoading() to mark the LindiViewModel as loading and resets any previous error.
  • Call setData(D data) to update the LindiViewModel with new data and stops loading.
  • Call setError(E error) to store an error.

LindiBuilder #

  • Listens to a single LindiViewModel.
  • Parameters:
    • viewModel: The LindiViewModel to listen to.
    • builder: A function that rebuilds the UI with the updated state.

LindiMultiBuilder #

  • Listens to multiple LindiViewModel instances.
  • Parameters:
    • viewModels: A list of LindiViewModel objects to listen to.
    • builder: A function that rebuilds the UI with the updated states.

LindiInjector #

  • Dependency injection for LindiViewModel objects.
  • Methods:
    • register<T>(T instance): Registers a LindiViewModel.
    • get<T>(): Retrieves a registered LindiViewModel instance.
    • exists<T>(): Check if an instance exists.
    • clear(): Clear all instances (optional for testing or cleanup).

Example Project #

For a complete example, check out the example folder in the repository.


License #

This project is licensed under the MIT License - see the LICENSE file for details.


Contributing #

We welcome contributions! Feel free to submit issues or pull requests to improve Lindi.


Happy coding with Lindi! 🚀

4
likes
160
points
228
downloads

Publisher

unverified uploader

Weekly Downloads

2024.08.05 - 2025.02.17

Lindi is a lightweight and reactive state management library for Flutter that simplifies building applications with dynamic UI updates.

Repository (GitHub)
Contributing

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on lindi