async_notifier 0.5.0 copy "async_notifier: ^0.5.0" to clipboard
async_notifier: ^0.5.0 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 'dart:async';

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>> getBooks() async {
    await Future<void>.delayed(const Duration(seconds: 1));
    return _books.toList();
  }
}

class TodosNotifier extends ChangeNotifier {
  TodosNotifier() {
    _books.addListener(notifyListeners);
  }

  final _repository = BookRepository();

  // Use `>>` to bind your ValueNotifier to this ChangeNotifier
  // Use ValueNotifier for synchronous data
  var _ascending = false;
  StreamSubscription<List<Book>>? _booksSubscription;

  // Use AsyncNotifier for asynchronous data
  final _books = AsyncNotifier<List<Book>>();

  AsyncSnapshot<List<Book>> get snapshot => _books.snapshot
      .whenData((list) => isAscending ? list : list.reversed.toList());

  bool get isAscending => _ascending;

  void toggleSort() {
    _ascending = !_ascending;
    notifyListeners();
  }

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

  void streamBooks() {
    _booksSubscription = _repository.streamBooks().listen(setBooks);
  }

  void setBooks(List<Book> books) {
    _books.future = Future.value(books);
  }

  void addBook(Book book) {
    // repository.saveBooks([...books, book]);
    fetchBooks();
  }

  void removeBook(Book book) {}

  @override
  void dispose() {
    _books.dispose();
    _booksSubscription?.cancel();
    super.dispose();
  }
}

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, _) {
                final list = notifier.snapshot.data ?? [];
                if (notifier.snapshot.isLoading) {
                  return const CircularProgressIndicator();
                }
                return ListView.builder(
                  itemCount: list.length,
                  itemBuilder: (context, index) {
                    final todo = list[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
160
points
143
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

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on async_notifier