我希望在我的应用启动时尽快在屏幕上显示小部件。在向用户显示小部件之后,我想先进行一些应用初始化(例如,设置数据库),然后再通过按下另一个屏幕离开启动屏幕。我不知道将应用程序初始化代码放在哪里。类似iOS上的viewDidAppear
。
这是我根据initState
尝试的结果。
class Launch extends StatefulWidget {
@override
_LaunchState createState() {
return _LaunchState();
}
}
class _LaunchState extends State<Launch> {
@override
Widget build(final BuildContext context) {
print('LaunchState build start');
final Widget w = Center(
child: Text('Launching...'),
);
print('LaunchState build end');
return w;
}
@override
void initState() {
print('LaunchState initState start');
super.initState();
print('LaunchState initState middle');
_appInitialization();
print('LaunchState initState end');
}
void _appInitialization() {
print('LaunchState _appInitialization');
}
}
输出为
flutter: LaunchState initState start
flutter: LaunchState initState middle
flutter: LaunchState _appInitialization
flutter: LaunchState initState end
flutter: LaunchState build start
flutter: LaunchState build end
我想看到的输出是
flutter: LaunchState build start
flutter: LaunchState build end
flutter: LaunchState initState start
flutter: LaunchState initState middle
flutter: LaunchState _appInitialization
flutter: LaunchState initState end
也许我正在以一种非常轻松的方式来解决这个问题。如果有完全不同的方法,我会为之倾心。
解决方案
感谢Mangaldeep Pannu的回答,看来我想念async
。
class Launch extends StatefulWidget {
@override
_LaunchState createState() {
return _LaunchState();
}
}
class _LaunchState extends State<Launch> {
@override
Widget build(final BuildContext context) {
print('LaunchState build start');
final Widget w = Center(
child: Text('Launching...'),
);
print('LaunchState build end');
return w;
}
@override
void initState() {
print('LaunchState initState start');
super.initState();
print('LaunchState initState middle');
_appInitialization(); // no await
print('LaunchState initState end');
}
void _appInitialization() async {
print('LaunchState _appInitialization begin');
// simulate some time consuming initialization task
await Future.delayed(Duration(seconds: 5));
print('LaunchState _appInitialization middle');
Navigator.push(...);
print('LaunchState _appInitialization end');
}
}
结果是
flutter: LaunchState initState start
flutter: LaunchState initState middle
flutter: LaunchState _appInitialization begin
flutter: LaunchState initState end
flutter: LaunchState build start
flutter: LaunchState build end
[5 second pause]
flutter: LaunchState _appInitialization middle
flutter: LaunchState _appInitialization end
答案 0 :(得分:1)
在应用启动时打开的第一个小部件中
@override
void initState() {
onStart();
}
void onStart() async {
await loadData(); //load your data here
Navigator.push(); //push to next screen
}
onStart
将异步加载数据。
然后,当数据加载完毕时,推到下一个屏幕。
答案 1 :(得分:1)
我们可以使用BLoC来解决这个问题。
创建一个 app_bloc.dart
文件,并按如下所示显示AppBloc
class
:
import 'dart:async';
final appBloc = AppBloc();
enum AppEvent{
onStart, onAppInitialized, onStop
}
class AppBloc {
final _appEventController = StreamController<AppEvent>.broadcast();
Stream<AppEvent> get appEventsStream => _appEventController.stream;
dispatch(AppEvent event) {
switch(event) {
case AppEvent.onStart:
_initializeApp();
_sinkEvent(AppEvent.onStart);
break;
case AppEvent.onStop:
_dispose();
_sinkEvent(AppEvent.onStop);
break;
case AppEvent.onAppInitialized:
_sinkEvent(AppEvent.onAppInitialized);
break;
}
}
void _sinkEvent(AppEvent appEvent) => _appEventController.sink.add(appEvent);
_dispose() {
_appEventController.close();
}
void _initializeApp() async {
await DBProvider.db.initDB();
dispatch(AppEvent.onAppInitialized); // will execute when all initializations are complete,
}
}
创建一个 database.dart
文件,并将其中的DBProvider
class
放在其中:
class DBProvider {
static final DBProvider _instance = new DBProvider._internal();
static final db = DBProvider();
factory DBProvider() {
return _instance;
}
DBProvider._internal();
initDB() async {
// todo initialize your database here.
}
}
您的主文件应如下所示:
import 'package:flutter/material.dart';
import 'package:st_overflow/app_bloc.dart';
void main() => runApp(App());
class App extends StatefulWidget {
App() {
appBloc.dispatch(AppEvent.onStart);
}
@override
_AppState createState() => _AppState();
}
class _AppState extends State<App> {
@override
Widget build(BuildContext context) {
return Launch();
}
@override
void dispose() {
appBloc.dispatch(AppEvent.onStop);
super.dispose();
}
}
,并在您的 Launch
Widget
中使用StreamBuilder消耗onAppInitialize事件,如下所示:
StreamBuilder(
stream: appBloc.appEventsStream,
builder: (context, snapshot){
switch (snapshot.data) {
case AppEvent.onAppInitialized:
// remove your Launch widget and show Screen 1 of your app (may be dashboard or something).
break;
}
},
);