Flutter 应用程序启动时如何设置数据库?

Ted*_*nry 7 dart flutter

我想在我的应用程序启动时尽快在屏幕上显示一个小部件。在向用户显示小部件后,我想在通过推动另一个屏幕离开启动屏幕之前进行一些应用程序初始化(例如设置数据库)。我不知道把我的应用程序初始化代码放在哪里。类似于viewDidAppeariOS 上的东西。

这是我基于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');
  }

}
Run Code Online (Sandbox Code Playgroud)

输出是

flutter: LaunchState initState start
flutter: LaunchState initState middle
flutter: LaunchState _appInitialization
flutter: LaunchState initState end
flutter: LaunchState build start
flutter: LaunchState build end
Run Code Online (Sandbox Code Playgroud)

我想我想看到的输出是

flutter: LaunchState build start
flutter: LaunchState build end
flutter: LaunchState initState start
flutter: LaunchState initState middle
flutter: LaunchState _appInitialization
flutter: LaunchState initState end
Run Code Online (Sandbox Code Playgroud)

也许我正在以一种非常不颤动的方式来解决这个问题。如果有一种完全不同的方法,我会全力以赴。

解决方案

感谢 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');
  }

}
Run Code Online (Sandbox Code Playgroud)

结果是

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
Run Code Online (Sandbox Code Playgroud)

Man*_*nnu 6

在应用程序启动时打开的第一个小部件中

@override
void initState() {
  onStart();
}

void onStart() async {
  await loadData();  //load your data here
  Navigator.push();  //push to next screen
}
Run Code Online (Sandbox Code Playgroud)

onStart异步加载数据。
当数据加载时推送到下一个屏幕。


Kal*_*ani 6

好吧,我们可以用 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,
  }
}
Run Code Online (Sandbox Code Playgroud)

创建一个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.
  }
}
Run Code Online (Sandbox Code Playgroud)

你的主文件应该是这样的:

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();
  }
}
Run Code Online (Sandbox Code Playgroud)

并在您使用 StreamBuilder 使用 onAppInitialize 事件时,如下所示:Launch Widget

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;        
        }
    },
);
Run Code Online (Sandbox Code Playgroud)