[英]How to change the state of a Switch in a Stateful Widget, retrieving data from a Provider?
I have a Switch on a screen and I need it to use the value that is in a Provider.我在屏幕上有一个 Switch,我需要它来使用 Provider 中的值。 I've tried to infer this value using the provider's value, but the Switch is immobile, it doesn't change visually(but the value is changed in the DB), it only works as it should when I remove the provider's inferences.
我尝试使用提供者的值来推断这个值,但是 Switch 是不动的,它不会在视觉上发生变化(但是数据库中的值会发生变化),它只有在我删除提供者的推论时才能正常工作。
My Provider: (It is being called when I start the application)我的提供者:(当我启动应用程序时它被调用)
class DailyDatabase with ChangeNotifier {
bool notificationActive = false;
void loadDailyData() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
notificationActive = prefs.getBool('notificationActive') ?? false;}
Variable:多变的:
@override
Widget build(BuildContext context) {
final provider = Provider.of<DailyDatabase>(context);
_notificationActive = provider.notificationActive;
Switch:转变:
Switch(
value: _notificationActive,
onChanged: (value) {
_notificationActive = value;
provider.setNotification(value);
},
),
You have to add setState((){});
您必须添加
setState((){});
which rebuild the screen and display changes on your screen重建屏幕并在屏幕上显示更改
Here's a very basic example of Provider
with a Switch
and using StatefulWidget
and its setState
to refresh the widget (instead of using ChangeNotifierProvider
and Consumer
to "listen" and "localize" the widget rebuild to just the Switch
and the Text
label, which is perhaps a more typical use):这是一个非常基本的带有
Switch
的Provider
示例并使用StatefulWidget
及其setState
来刷新小部件(而不是使用ChangeNotifierProvider
和Consumer
来“侦听”和“本地化”小部件重建为Switch
和Text
label,这可能是更典型的用法):
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class SwitchProviderPage extends StatefulWidget {
@override
_SwitchProviderPageState createState() => _SwitchProviderPageState();
}
class Database {
bool active = false;
void setActive(bool value) {
active = value;
}
}
class _SwitchProviderPageState extends State<SwitchProviderPage> {
@override
Widget build(BuildContext context) {
return Provider(
create: (context) => Database(),
child: Builder(
builder: (context) {
Database db = Provider.of<Database>(context, listen: false);
return Scaffold(
appBar: AppBar(
title: Text('Switch Field'),
),
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Active? ${db.active}'),
Switch(
onChanged: (val) { // ← remember to use val (bool)
print('Switch value: $val');
setState(() {
db.setActive(val);
// this sets the Switch setting on/off
});
},
value: db.active,
)
],
),
),
),
);
},
),
);
}
}
Note :注意:
The use of Builder
in above is only to make Scaffold
be a child of Provider
.上面使用
Builder
只是为了让Scaffold
成为Provider
的子级。 Otherwise, Scaffold
would be a sibling, not a child, and Provider
will not work.否则,
Scaffold
将是兄弟姐妹,而不是孩子,并且Provider
将无法工作。 Since you wrap your entire app in your ChangeNotifierProvider
, you don't need to do this.由于您将整个应用程序包装在
ChangeNotifierProvider
中,因此您不需要这样做。 I needed to do this to get a self-contained example.我需要这样做以获得一个独立的示例。
Here's a complete app example (copy paste into main.dart, replacing everything on page) using a StatelessWidget
and the typical/common ChangeNotifierProvider
& Consumer
.这是一个完整的应用示例(将粘贴复制到 main.dart,替换页面上的所有内容)使用
StatelessWidget
和典型/常见的ChangeNotifierProvider
和Consumer
。
This version uses a mocked long duration async call when flipping Switch
.此版本在翻转
Switch
时使用模拟的长时间异步调用。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(ChangeNotifierProvider<DatabaseListenable>(
create: (context) => DatabaseListenable(),
child: MyApp())
);
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Provider Demo App',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: StatelessSwitchProviderPage(),
);
}
}
class DatabaseListenable with ChangeNotifier {
bool active = false;
Future<void> setActive(bool value) async {
// Mock slow database call ↓
await Future.delayed(Duration(milliseconds: 500), () {
active = value;
print('Async DB call DONE.');
});
notifyListeners(); // ← causes Consumer to rebuild
}
}
class StatelessSwitchProviderPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Switch Provider Stateless'),
),
body: SafeArea(
child: Center(
child: Consumer<DatabaseListenable>(
builder: (context, db, child) => Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Active? ${db.active}'),
Switch(
onChanged: (val) {
print('Switch value: $val');
db.setActive(val);
},
value: db.active,
)
],
),
),
),
),
);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.