我有一个应用程序,它使用包含一些数据的本地通知。在这种情况下,它是从 JSON 文件中读取的一些引号。
我想做的是每分钟阅读另一篇引文并在主屏幕中更新。
void main() {
runApp(ChangeNotifierProvider<QuotesRepository>(
create: (context) => QuotesRepository.instance(),
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: MyApp(),
),
));
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
var quote = Provider.of<QuotesRepository>(context);
quote.showScheduledNotification();
return Scaffold(
appBar: new AppBar(
backgroundColor: Colors.red,
title: new Text('Flutter notification demo'),
),
body: new Center(
child: Text(
quote.lastMessage.toString(),
style: GoogleFonts.clickerScript(fontSize: 40.0),
),
),
);
}
}
这是定义提供者的地方:
class QuotesRepository with ChangeNotifier {
String? lastMessage;
QuotesRepository.instance();
Future<void> loadJson(int index) async {
String data = await rootBundle.loadString('assets/quotes.json');
Map<String, dynamic> userMap = jsonDecode(data);
this.lastMessage = userMap['quotes'][index]['quote'];
}
Future<void> showScheduledNotification() async {
int randomValue = 42;
await loadJson(randomValue).then((value) => showNotificationBody());
notifyListeners();
}
Future<void> showNotificationBody() async {
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
print("Function called");
const androidPlatformChannelSpecifics = AndroidNotificationDetails(
'channel id',
'channel name',
'channel description',
icon: 'flutter_devs',
largeIcon: DrawableResourceAndroidBitmap('flutter_devs'),
);
var iOSPlatformChannelSpecifics = IOSNotificationDetails();
const NotificationDetails platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics,
);
flutterLocalNotificationsPlugin.periodicallyShow(0, '365<3',
this.lastMessage, RepeatInterval.everyMinute, platformChannelSpecifics,
payload: this.lastMessage);
}
}
然而,这会每秒调用该函数并导致应用程序崩溃。
我知道这是因为我调用 quote.showScheduledNotification();
和 notifyListeners()
会导致它进入无限循环。
但是如何防止这种情况发生?如何仅加载一次,然后在每次通知到达时更新 lastMessage
。
为了简单起见,我每次都显示相同的引用 (42)。
答案 0 :(得分:1)
似乎您正在寻找 init 功能。如果您将 MyApp
转换为有状态小部件,您将能够使用 stateful
小部件的 init 方法。这应该可以解决一部分问题。您几乎不应该在 build
函数中使用 init 功能,因为它会经常被调用。
class MyApp extends StatefulWidget {
const MyApp();
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
var quote = Provider.of<QuotesRepository>(context);
quote.showScheduledNotification();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
backgroundColor: Colors.red,
title: new Text('Flutter notification demo'),
),
body: new Center(
child: Text(
Provider.of<QuotesRepository>(context).lastMessage.toString(),
style: GoogleFonts.clickerScript(fontSize: 40.0),
),
),
);
}
}