I would like to show a widget on the screen as quickly as possible when my app launches. After the widget has been shown to the user, I'd like to do some app initialization (e.g. set up a database) before leaving the launch screen by pushing another screen. I cannot figure out where to put my app initialization code. Something analogous to viewDidAppear
on iOS.
This is what I tried based on 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');
}
}
The output was
flutter: LaunchState initState start
flutter: LaunchState initState middle
flutter: LaunchState _appInitialization
flutter: LaunchState initState end
flutter: LaunchState build start
flutter: LaunchState build end
The output I think I want to see is
flutter: LaunchState build start
flutter: LaunchState build end
flutter: LaunchState initState start
flutter: LaunchState initState middle
flutter: LaunchState _appInitialization
flutter: LaunchState initState end
Maybe I'm going about this in a very un-flutter way. If there is a completely different approach, I'm all ears.
SOLUTION
Thanks to Mangaldeep Pannu's answer, it appears I'm missing 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');
}
}
The results are
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
A MySQL driver for the Dart programming language. Works on Flutter and on the server. This library aims to provide an easy to use interface to MySQL.
In your first widget that opens when the app starts
@override
void initState() {
onStart();
}
void onStart() async {
await loadData(); //load your data here
Navigator.push(); //push to next screen
}
onStart
will load the data asynchronously.
And when the data gets loaded push to next screen.
Well we can handle this with BLoC.
create a app_bloc.dart
file and have AppBloc
class
as shown bellow in it:
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,
}
}
create a database.dart
file and have your DBProvider
class
in it:
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.
}
}
You should have your main file something like this:
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();
}
}
and in your Launch
Widget
consume the onAppInitialize event using StreamBuilder like this:
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;
}
},
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With