0

I am trying to connect to a static database as it is explained in this answer. I therefore created an asynchronous function that looks like this:

Future<void> loadDataBase() async {
  // Construct a file path to copy database to
  Directory documentsDirectory = await getApplicationDocumentsDirectory();
  String path = join(documentsDirectory.path, "asset_worldcities.db");

  // Only copy if the database doesn't exist
  if (FileSystemEntity.typeSync(path) == FileSystemEntityType.notFound) {
    // Load database from asset and copy
    ByteData data = await rootBundle.load(join('assets', 'worldcities.db'));
    List<int> bytes = data.buffer.asUint8List(
        data.offsetInBytes, data.lengthInBytes);

    // Save copied asset to documents
    await new File(path).writeAsBytes(bytes);
  }
}

Now I thought I could access my database inside my main widget by using this function and then call

Directory appDocDir = await getApplicationDocumentsDirectory();
String databasePath = join(appDocDir.path, 'asset_database.db');
this.db = await openDatabase(databasePath);
initialized = true;
Future<List<Page>> search(String word, int parentId) async {
    if (!initialized) await this._initialize();
    String query = '''
      SELECT * FROM users
      LIMIT 25''';
    return await this.db.rawQuery(query);
}

but this way I am not allowed to use this.db and also not await as I am not inside an async function. Where do I need to put this database request so that it works?

6
  • I would put anything like getApplicationDocumentsDirectory or openDatabase inside main before runApp. For search you should use FutureBuilder. Commented Oct 7, 2020 at 20:57
  • Hi thanks for your comment! Then I need to make main an asynchronous function, correct? Commented Oct 7, 2020 at 21:02
  • This seems not to be allowed :/ Commented Oct 7, 2020 at 21:04
  • You can definitely make main an asynchronous function, all my apps do. You might have to do a flutter clean before building again. Commented Oct 7, 2020 at 21:14
  • Android Studio marks the async with red underline and says Unexpected text async if I do void main() asnyc {. How can I prevent this? Commented Oct 7, 2020 at 21:22

1 Answer 1

1

Depending whether you need to do this every time and the database could grow, or whether it's a one-time operation (which it seems like it might be?) and the database is small enough that it's not going to take long to query it, there are different approaches I'd take.

If it's a one-time per install sort of thing and the database will always be small, making the user wait while it copies the file across probably isn't a huge deal. In that case I'd do something like this:

main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  if (needToLoadDatabase()) {
    await loadDatabase();
  }

  let users = await queryUsers();

  runApp(MainWidget(users: users));
}

However, if you're reading from the database and it's something that could take any significant amount of time, I'd recommend initiating the load and then passing the future into your main widget, where it could use a FutureBuilder to build an intermediate UI.

That'd look something like this:

main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  let loadUsers = () async {
    if (needToLoadDatabase()) {
      await loadDatabase();
    }

    return await queryUsers();
  }();


  runApp(MainWidget(loadUsers: loadUsers));
}

class MainApp extends StatelessWidget {

  final Future<Users> loadUsers;

  MainApp({@required this.loadUsers, Key key}): super(key: key);

  Widget build(BuildContext context) {
    return FutureBuilder(
      builder: (ctx, snapshot) {
        if (snapshot.hasData) {
          // build your UI with data
        } else {
          // build your UI without data
        }
      }
    );
  }
}

Also note that there's no reason you have to do the loading in the main function - you could make your widget stateful and kick that off in the initState, or any number of places like directly where you use the list. You could also look at the FutureProvider from the Provider package.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for this thorough answer! I think I will open another question for my strange async issue and then I can hopefully come back here and implement the database access.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.