我想在我的应用程序启动时尽快在屏幕上显示一个小部件。在向用户显示小部件之后,我想通过按下另一个屏幕在离开启动屏幕之前进行一些应用初始化(例如,设置数据库)。我无法弄清楚我的应用初始化代码放在哪里。类似于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
在应用程序启动时打开的第一个小部件中
@override
void initState() {
onStart();
}
void onStart() async {
await loadData(); //load your data here
Navigator.push(); //push to next screen
}
onStart
将异步加载数据。
当数据加载后推送到下一个屏幕。
我们可以用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;
}
},
);