Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I setup a database when Flutter app launches?

Tags:

flutter

dart

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
like image 919
Ted Henry Avatar asked Apr 14 '19 03:04

Ted Henry


People also ask

Is MySQL good for Flutter?

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.


2 Answers

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.

like image 147
Mangaldeep Pannu Avatar answered Oct 15 '22 00:10

Mangaldeep Pannu


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;        
        }
    },
);
like image 44
Kalpesh Kundanani Avatar answered Oct 15 '22 00:10

Kalpesh Kundanani