async_notifier 0.3.2 copy "async_notifier: ^0.3.2" to clipboard
async_notifier: ^0.3.2 copied to clipboard

A ValueNotifier for all async states. Listen, notify, and manage loading, error and data in one place.

example/lib/main.dart

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

void main() {
  runApp(MainApp(notifier: TodosNotifier()));
}

class Book {
  const Book({required this.id, required this.title});
  final String title;
  final int id;

  @override
  operator ==(Object other) => other is Book && other.id == id;

  @override
  int get hashCode => id.hashCode;
}

class BookRepository {
  static final _books = {
    const Book(id: 0, title: 'The Book of Spells'),
    const Book(id: 1, title: 'The Darkhold'),
    const Book(id: 2, title: "The Hitchhiker's Guide to the Galaxy"),
    const Book(id: 3, title: 'The Dark Note'),
    const Book(id: 4, title: 'Book of Cagliostro'),
    const Book(id: 5, title: 'Tome of Stilled Tongue'),
  };

  Future<void> saveBooks(List<Book> books) async {
    await Future<void>.delayed(const Duration(seconds: 1));
    _books.clear();
    _books.addAll(books);
  }

  Stream<List<Book>> streamBooks() async* {
    await Future<void>.delayed(const Duration(seconds: 1));
    yield _books.toList();
  }

  Future<List<Book>> fetchBooks() async {
    await Future<void>.delayed(const Duration(seconds: 1));
    return _books.toList();
  }
}

class TodosNotifier extends ChangeNotifier {
  TodosNotifier() {
    fetchBooks();
  }

  final _repository = BookRepository();
  final messengerkey = GlobalKey<ScaffoldMessengerState>();

  // Use `sync` to bind your ValueNotifier to this ChangeNotifier
  // Use ValueNotifier for synchronous data
  late final _ascending = ValueNotifier(true).sync(this);

  // Use AsyncNotifier for asynchronous data
  late final _books = AsyncNotifier(<Book>[], onData: _onData).sync(this);

  void _onData(List<Book> books) async {
    await _repository.saveBooks(books);
    messengerkey.currentState?.showSnackBar(
      const SnackBar(content: Text('Saved books with success!')),
    );
  }

  List<Book> get books {
    final list = isAscending ? _books.value : _books.value.reversed;
    return list.toList();
  }

  String? get errorMessage => _books.error?.toString();

  bool get isLoading => _books.isLoading;

  bool get isAscending => _ascending.value;

  void toggleSort() {
    _ascending.value = !_ascending.value;
  }

  void fetchBooks() {
    _books.stream = _repository.streamBooks();
  }

  void streamBooks() {
    _books.future = _repository.fetchBooks();
  }

  void addBook(Book book) {
    _books.value = books..add(book);
  }

  void removeBook(Book book) {
    _books.value = books..remove(book);
  }
}

class MainApp extends StatelessWidget {
  const MainApp({super.key, required this.notifier});

  final TodosNotifier notifier;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      scaffoldMessengerKey: notifier.messengerkey,
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: const Text('AsyncNotifier'),
          actions: [
            IconButton(
              icon: const Icon(Icons.refresh),
              onPressed: notifier.fetchBooks,
            ),
            IconButton(
              icon: const Icon(Icons.sort),
              onPressed: () => notifier.toggleSort(),
            ),
          ],
        ),
        body: Center(
          child: RefreshIndicator(
            onRefresh: () async => notifier.fetchBooks(),
            child: ListenableBuilder(
              listenable: notifier,
              builder: (context, _) {
                if (notifier.isLoading) {
                  return const CircularProgressIndicator();
                }
                return ListView.builder(
                  itemCount: notifier.books.length,
                  itemBuilder: (context, index) {
                    final todo = notifier.books[index];

                    return ListTile(
                      title: Text(todo.title),
                      trailing: IconButton(
                        icon: const Icon(Icons.delete),
                        onPressed: () => notifier.removeBook(todo),
                      ),
                    );
                  },
                );
              },
            ),
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            notifier.addBook(
              const Book(id: 7, title: 'The 7 Wonders'),
            );
          },
          child: const Icon(Icons.add),
        ),
      ),
    );
  }
}
4
likes
0
points
144
downloads

Publisher

verified publisherbranvier.com

Weekly Downloads

A ValueNotifier for all async states. Listen, notify, and manage loading, error and data in one place.

Homepage
Repository (GitHub)
View/report issues

Topics

#async #value #notifier #state

License

unknown (license)

Dependencies

flutter

More

Packages that depend on async_notifier