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

时间:2019-04-14 03:21:00

标签: dart flutter

我希望在我的应用启动时尽快在屏幕上显示小部件。在向用户显示小部件之后,我想先进行一些应用初始化(例如,设置数据库),然后再通过按下另一个屏幕离开启动屏幕。我不知道将应用程序初始化代码放在哪里。类似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

2 个答案:

答案 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;        
        }
    },
);