import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
/// provider的创建和读取,以及如何在main方法中初始化provider
/// 所有provider都必须放到全局变量,并且加final,
/// 可以用于创建一个Service单例,provider默认是lazy的,第一次使用时provider时才会创建Service
/// 快速创建provider可以使用 Android Studio plugin :Flutter Riverpod Snippets ,
final _serviceProvider = Provider<_Service>((ref) {
return _Service();
});
class _Service {
int count = 10;
}
///可以在provider create方法中读取其他provider
final _pushUtilProvider = Provider<_PushUtil>((ref) {
print("从provider create 方法 中读取provider ${ref.read(_serviceProvider).count}");
return _PushUtil();
});
class _PushUtil {}
///或直接将ref传入PushUtil
final pushUtilProvider1 = Provider<_PushUtil1>((ref) {
return _PushUtil1(ref);
});
class _PushUtil1 {
_PushUtil1(this.ref);
Ref ref;
void test() {
print("从provider 中读取provider ${ref.read(_serviceProvider).count}");
}
}
class ProviderPage extends ConsumerWidget {
const ProviderPage(this.title, {Key? key}) : super(key: key);
final String title;
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(title: Text(title)),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
"在widget中读取provider: ",
style: TextStyle(color: Colors.red),
),
///在widget 中读取provider有三种方式,都需要通过使用WidgetRef.read
///第一种使用Consumer,builder方法的第二个参数就是WidgetRef
Consumer(
builder: (_, ref, __) {
return Text("使用Cosnumer 读取provider: ${ref.read(_serviceProvider).count}");
},
),
///第二种使用ConsumerWidget
const _TestConsumerWidget(),
///第二种使用ConsumerStatefulWidget
const _TestConsumerStatefulWidget(),
const SizedBox(height: 20),
const Text(
"在provider 中读取其他provider: ",
style: TextStyle(color: Colors.red),
),
ElevatedButton(
onPressed: () {
/// 因为provider是懒加载的, 所以provider create方法只会在第一次使用的时候调用
ref.read(_pushUtilProvider);
},
child: const Text("从provider create 方法中读取其他provider"),
),
ElevatedButton(
onPressed: () {
/// 因为provider是懒加载的, 所以如果想要在APP一开始就初始化,比如flutter_sdk_base中的PushUtil,例如
/// https://gitlab.xixitime.com/flutter/app/flutter_partner_training_ai/blob/dev_v2.7.0/lib/providers/push_util_provider.dart
/// 需要将在main中添加
/// final container = ProviderContainer();
// container.read(pushUtilProvider1);
// runApp(UncontrolledProviderScope(
// container: container,
// child: const MyApp()));
ref.read(pushUtilProvider1).test();
},
child: const Text("从provider 中读取其他provider"),
),
],
),
),
);
}
}
/// ConsumerWidget == StatelessWidget,只不过在build方法中多了一个WidgetRef参数
/// 也可以使用Flutter Riverpod Snippets 快速创建
class _TestConsumerWidget extends ConsumerWidget {
const _TestConsumerWidget({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
return Text("使用CosnumerWidget 读取provider: ${ref.read(_serviceProvider).count}");
}
}
/// ConsumerWidget == StatefulWidget,只不过在state中多了一个WidgetRef属性
/// 也可以使用Flutter Riverpod Snippets 快速创建
class _TestConsumerStatefulWidget extends ConsumerStatefulWidget {
const _TestConsumerStatefulWidget({
Key? key,
}) : super(key: key);
@override
ConsumerState createState() => __TestConsumerStatefulWidgetState();
}
class __TestConsumerStatefulWidgetState extends ConsumerState<_TestConsumerStatefulWidget> {
@override
Widget build(BuildContext context) {
return Text("使用ConsumerStatefulWidget 读取provider: ${ref.read(_serviceProvider).count}");
}
}
ChangeNotifier
是 Flutter SDK 中的一个简单的类。它用于向监听器发送通知。换言之,如果被定义为 ChangeNotifier
,你可以订阅它的状态变化。(这和大家所熟悉的观察者模式相类似)。在 provider
中,ChangeNotifier
是一种能够封装应用程序状态的方法。对于特别简单的程序,你可以通过一个 ChangeNotifier
来满足全部需求。在相对复杂的应用中,由于会有多个模型,所以可能会有多个 ChangeNotifier
。 (不是必须得把 ChangeNotifier
和 provider
结合起来用,不过它确实是一个特别简单的类)。