Flutter异步通知插件async_notifier的使用
Flutter异步通知插件async_notifier的使用
AsyncNotifier
是一个用于处理所有异步状态的 ValueNotifier
。它允许监听、通知并管理加载、错误和数据状态,所有这些都集中在一个地方。
使用方法
AsyncNotifier
实质上是一个带有两个新设置器 future
和 stream
的 ValueNotifier
。它的所有状态都被解析为一个 AsyncSnapshot
。由于其特性,它可以很容易地与Flutter的原生小部件和类集成,使得使用起来简单直接。
简单示例
import 'package:async_notifier/async_notifier.dart';
void main() {
// 不需要初始值,默认为 AsyncSnapshot.nothing()
final counter = AsyncNotifier<int>();
// 可监听
counter.addListener(() {
print("New state: ${counter.snapshot}");
});
// 设置 future 或 stream
counter.future = Future.value(42);
counter.stream = Stream.fromIterable([1, 2, 3]);
// 获取快照
final AsyncSnapshot<int> snapshot = counter.snapshot;
// 使用扩展检查状态
snapshot.isLoading;
snapshot.isReloading;
snapshot.requireData;
snapshot.hasData;
snapshot.hasError;
snapshot.hasNone;
snapshot.error;
snapshot.stackTrace;
// 控制 future 或 stream
counter.cancel(); // 对 future 有效
counter.dispose();
// 解析状态
final result = counter.when(
data: (data) => 'Data $data',
error: (error, stackTrace) => 'Error $error',
loading: () => 'Loading',
);
// 或者使用 switch 表达式
final resultSwitch = switch (snapshot) {
AsyncSnapshot(:var data?) => 'Data $data',
AsyncSnapshot(:var error?) => 'Error $error',
_ => 'Loading',
};
}
状态管理
你可以直接监听所有 AsyncNotifier
状态,并将其绑定到其他对象。
class TodosNotifier extends ChangeNotifier {
TodosNotifier() {
_todos.addListener(notifyListeners);
fetchTodos();
}
final _todos = AsyncNotifier<List<Todo>>();
AsyncSnapshot<List<Todo>> get todosSnapshot => _todos.snapshot;
void fetchTodos() {
_todos.future = _repository.fetchTodos();
}
[@override](/user/override)
void dispose() {
_todos.dispose();
super.dispose();
}
}
消费状态
你可以使用Flutter的原生解决方案如 ListenableBuilder
来消费状态。
class TodoList extends StatelessWidget {
const TodoList({super.key, required this.todosNotifier});
final TodosNotifier todosNotifier;
[@override](/user/override)
Widget build(BuildContext context) {
return ListenableBuilder(
listenable: todosNotifier,
builder: (context, _) {
return todosNotifier.snapshot.when(
loading: () => const CircularProgressIndicator(),
error: (error, stackTrace) => Text('Error: $error'),
data: (data) => ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) => Text(data[index].title),
),
);
},
);
}
}
使用 provider
:
class TodoList extends StatelessWidget {
const TodoList({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
final todosSnapshot = context.watch<TodosNotifier>().snapshot;
return todosSnapshot.when(
loading: () => const CircularProgressIndicator(),
error: (error, stackTrace) => Text('Error: $error'),
data: (data) => ListView.builder(
itemCount: todosListenable.value.length,
itemBuilder: (context, index) => Text(data[index].title),
),
);
}
}
完整示例 Demo
以下是一个完整的示例,展示了如何使用 AsyncNotifier
来管理书籍列表的状态,并在UI中显示加载、错误和数据状态。
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](/user/override)
operator ==(Object other) => other is Book && other.id == id;
[@override](/user/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();
final _books = AsyncNotifier<List<Book>>();
AsyncSnapshot<List<Book>> get snapshot => _books.snapshot
.whenData((list) => isAscending ? list : list.reversed.toList());
bool get isAscending => _ascending;
var _ascending = false;
StreamSubscription<List<Book>>? _booksSubscription;
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) {
fetchBooks();
}
void removeBook(Book book) {}
[@override](/user/override)
void dispose() {
_books.dispose();
_booksSubscription?.cancel();
super.dispose();
}
}
class MainApp extends StatelessWidget {
const MainApp({super.key, required this.notifier});
final TodosNotifier notifier;
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
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 book = list[index];
return ListTile(
title: Text(book.title),
trailing: IconButton(
icon: const Icon(Icons.delete),
onPressed: () => notifier.removeBook(book),
),
);
},
);
},
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
notifier.addBook(
const Book(id: 7, title: 'The 7 Wonders'),
);
},
child: const Icon(Icons.add),
),
),
);
}
}
更多关于Flutter异步通知插件async_notifier的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter异步通知插件async_notifier的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter中使用async_notifier
插件来实现异步通知的示例代码。async_notifier
插件通常用于在后台任务完成时向UI发送通知。
首先,确保你已经在pubspec.yaml
文件中添加了async_notifier
依赖:
dependencies:
flutter:
sdk: flutter
async_notifier: ^x.y.z # 请替换为最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,我们编写一个简单的Flutter应用,展示如何使用async_notifier
。
1. 创建一个通知服务
首先,我们创建一个服务类,用于处理异步任务并发送通知。
import 'package:async_notifier/async_notifier.dart';
import 'dart:async';
class NotificationService {
final AsyncNotifier<String> notifier = AsyncNotifier<String>();
Future<void> performAsyncTask() async {
// 模拟一个耗时任务
await Future.delayed(Duration(seconds: 3));
// 任务完成后发送通知
notifier.notify("Task completed!");
}
}
2. 在UI中使用通知服务
接下来,我们在UI组件中使用这个服务,并监听通知。
import 'package:flutter/material.dart';
import 'package:async_notifier/async_notifier.dart';
import 'notification_service.dart'; // 假设你将上面的代码保存在这个文件里
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: NotificationScreen(),
);
}
}
class NotificationScreen extends StatefulWidget {
@override
_NotificationScreenState createState() => _NotificationScreenState();
}
class _NotificationScreenState extends State<NotificationScreen> {
final NotificationService _notificationService = NotificationService();
String _notificationMessage = "";
@override
void initState() {
super.initState();
// 订阅通知
_notificationService.notifier.subscribe((message) {
setState(() {
_notificationMessage = message;
});
});
// 启动异步任务
_notificationService.performAsyncTask();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Async Notifier Example"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"Notification Message:",
style: TextStyle(fontSize: 18),
),
SizedBox(height: 10),
Text(
_notificationMessage,
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
],
),
),
);
}
}
3. 运行应用
现在,你可以运行这个Flutter应用。当应用启动时,它会启动一个异步任务,并在任务完成后更新UI,显示“Task completed!”消息。
这个示例展示了如何使用async_notifier
插件来在Flutter应用中处理异步通知。你可以根据需要扩展这个示例,以处理更复杂的异步任务和通知逻辑。