在MaterialApp:onGenerateRoute中使用异步/未来数据库访问方法会导致错误

时间:2019-07-01 17:49:07

标签: flutter dart

我的规范很简单-我需要根据本地sqlite数据库中用户数量的值返回DeviceLoginPage()或RemoteLoginPage()。

这是我的app.dart ...

(app.dart)
class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'MyApp',
      initialRoute: '/login',
      onGenerateRoute: _getRoute,
      // Copy the platform from the main theme in order to support platform
      // toggling from the Gallery options menu.
      theme: _kShrineTheme.copyWith(platform: Theme.of(context).platform),
    );
  }
}

Route<dynamic> _getRoute(RouteSettings settings) {
  debugPrint("Inside _getRoute()");
  debugPrint("settings.name: " + settings.name);

  if (settings.name == '/login') {
    return MaterialPageRoute<void>(
      settings: settings,
        builder: (BuildContext context) => (AuthService().getLoginType() == LoginType.DEVICE.toString()) ?
    DeviceLoginPage() : RemoteLoginPage(),

      fullscreenDialog: true,
    );
  }
}

我检查我的用户表是否在我的authentication.dart AuthService.getLoginType()中包含任何用户

(authentication.dart)
abstract class BaseAuth {
  Future<String> signIn(String email, String phone, String password);

  Future<String> signUp(String email, String phone);

  Future<void> signOut();
}

enum LoginType {
  DEVICE,
  REMOTE,
}

class AuthService implements BaseAuth {

  DatabaseService _database = new DatabaseService();

  ...

  Future<String> getLoginType() async {
    print("Inside getLoginType()");
    int usersCount = await _database.getUsersCount();
    print("count in auth is:" + usersCount.toString());
    print("Returning LoginType:" + (usersCount >=1 ? LoginType.DEVICE.toString() : LoginType.REMOTE.toString()));
    return usersCount >=1 ? LoginType.DEVICE.toString() : LoginType.REMOTE.toString();
  }
}

最后是我的database.dart文件

class DatabaseService {
  static final DatabaseService _instance = DatabaseService.internal();
  factory DatabaseService() => _instance;

  Database _database;

  Future<Database> get db async {
    print("Inisde DatabaseService.get db");
    if (_database != null) {
      print("_database is not null");
      return _database;
    }
    _database = await initDatabase();
    return _database;
  }

  DatabaseService.internal();

  initDatabase() async {
    print("Inisde DatabaseService.initDatabase");
    print("Here 1...");
    Directory documentDirectory;
    try {
      print("About to run getApplicationDocumentsDirectory()...");
      documentDirectory = await getApplicationDocumentsDirectory();
      print("Got it: " + documentDirectory.toString());
    } catch (ex) {
      print("await getApplicationDocumentsDirectory() ERROR:" + ex.toString());
    }
    print("Here 2...");
    String path = join(documentDirectory.path, "myapp.db");
    print("Here 3...");
    var ourDb = await openDatabase(path, version: 1, onCreate: _onCreate);
    print("Here 4...");
    print("ourDb is: " + ourDb.toString());
    return ourDb;
  }

  void _onCreate(Database db, int version) async {
    print("Running _onCreate()");
    await db.execute(
        "CREATE TABLE User(id INTEGER PRIMARY KEY, firstname TEXT, lastname TEXT, username TEXT, password TEXT)");
    print("Table is created");
    await db.rawInsert('INSERT INTO User(firstname,lastname,username,password) VALUES ("Anne","Suzanne","anne@gmail.com","anne")');
  }

  Future<int> getUsersCount() async {
    final dbClient = await db;
    var res = await dbClient.rawQuery('SELECT COUNT(*) FROM User');
    int count = Sqflite.firstIntValue(res);
    print("count is:" + count.toString());
    return count;
  }
}

问题是在应用程序启动时既未加载DeviceLoginPage()也未加载RemoteLoginPage()。相反,我得到了堆栈跟踪...

Syncing files to device TECNO P701...
I/flutter ( 9247): Inside _getRoute()
I/flutter ( 9247): settings.name: /
I/flutter ( 9247): Inside _getRoute()
I/flutter ( 9247): settings.name: /login
I/flutter ( 9247): ══╡ EXCEPTION CAUGHT BY FLUTTER FRAMEWORK ╞═════════════════════════════════════════════════════════
I/flutter ( 9247): The following message was thrown:
I/flutter ( 9247): Could not navigate to initial route.
I/flutter ( 9247): The requested route name was: "/login"
I/flutter ( 9247): The following routes were therefore attempted:
I/flutter ( 9247):  * /
I/flutter ( 9247):  * /login
I/flutter ( 9247): This resulted in the following objects:
I/flutter ( 9247):  * null
I/flutter ( 9247):  * MaterialPageRoute<Widget>(RouteSettings("/login", null), animation: null)
I/flutter ( 9247): One or more of those objects was null, and therefore the initial route specified will be ignored and
I/flutter ( 9247): "/" will be used instead.
I/flutter ( 9247): ════════════════════════════════════════════════════════════════════════════════════════════════════
I/flutter ( 9247): Inside _getRoute()
I/flutter ( 9247): settings.name: /
I/flutter ( 9247): Another exception was thrown: Could not find a generator for route RouteSettings("/", null) in the _WidgetsAppState.
D/OpenGLRenderer( 9247): ProgramCache.generateProgram: 34359738369
D/GraphicBuffer( 9247): register, handle(0xa42be7d0) (w:600 h:1024 s:608 f:0x1 u:0x000f02)
I/SurfaceView( 9247): updateWindow -- setFrame, this = io.flutter.view.FlutterView{5a56df6 VFED..... .F...... 0,0-600,960}
V/Activity( 9247): onPause com.techparadigms.mymandate.MainActivity@61099a0
V/Activity( 9247): onSaveInstanceState com.techparadigms.mymandate.MainActivity@61099a0: Bundle[{android:viewHierarchyState=Bundle[{android:views={16908290=android.view.AbsSavedState$1@1f17839}}]}]
D/SurfaceView( 9247): 94727670 windowPositionLostRT RT, frameNr = 0
V/Activity( 9247): onStop com.techparadigms.mymandate.MainActivity@61099a0
W/IInputConnectionWrapper( 9247): getExtractedText on inactive InputConnection
W/IInputConnectionWrapper( 9247): getTextBeforeCursor on inactive InputConnection
I/art     ( 9247): Enter while loop.
I/art     ( 9247): Enter while loop.
V/Activity( 9247): onStart com.techparadigms.mymandate.MainActivity@61099a0
V/Activity( 9247): onResume com.techparadigms.mymandate.MainActivity@61099a0
V/PhoneWindow( 9247): DecorView setVisiblity: visibility = 0, Parent = ViewRoot{fb27382 com.techparadigms.mymandate/com.techparadigms.mymandate.MainActivity,ident = 0}, this = DecorView@5a05959[MainActivity]
V/Activity( 9247): onPause com.techparadigms.mymandate.MainActivity@61099a0
V/Activity( 9247): onSaveInstanceState com.techparadigms.mymandate.MainActivity@61099a0: Bundle[{android:viewHierarchyState=Bundle[{android:views={16908290=android.view.AbsSavedState$1@1f17839}}]}]
V/Activity( 9247): onStop com.techparadigms.mymandate.MainActivity@61099a0
D/GraphicBuffer( 9247): register, handle(0x91551650) (w:600 h:960 s:608 f:0x1 u:0x000f02)
I/art     ( 9247): Enter while loop.

仔细检查后,我发现一切正常,直到print("Here 1...");中的诊断行initDatabase() async function (database.dart)。似乎在这里暂停执行...不打印其他诊断行"Here 2...".然后继续评估该行

    builder: (BuildContext context) => (AuthService().getLoginType() == LoginType.DEVICE.toString()) ?
    DeviceLoginPage() : LoginPage(),

找不到有效的路由,因为getLoginType()返回空值。 我在Flutter中相对较新。到目前为止,我一直在使用在flutter_gallery_example中使用的onGenerateRoute()示例……请问实现这一目标的最佳方法是什么?现在已经失去睡眠将近一个星期了...谢谢您的协助

0 个答案:

没有答案