← Technology Archive

Historical archive

Persisting Flutter App State with sqflite

A small Flutter example that wraps sqflite database operations and uses a stored launch counter to choose between welcome and waiting screens.

Flutter apps commonly use one of two approaches for local persistence:

  • shared_preferences stores simple key-value data in a local file and feels similar to browser localStorage.
  • sqflite provides a complete local SQLite database.

Database wrapper

The following class wraps basic database initialization, querying, and updating:

import 'package:sqflite/sqflite.dart';

class SqlLite {
  final sqlFileName = "bonfire.sql";
  final userState = "userState";
  Database db;

  open() async {
    String path = "${await getDatabasesPath()}/$sqlFileName";
    if (db == null) {
      db = await openDatabase(path, version: 1, onCreate: (db, ver) async {
        await db.execute("""
        Create Table userState(
         welComeTimes int,
         code int
        );
        """);
        await db.insert("userState", {'welComeTimes': 0, 'code': 200});
      });
    }
  }

  queryUserState() async {
    return await db.query(userState, columns: null);
  }

  insertUserState(Map<String, dynamic> m) async {
    return await db.update(userState, m);
  }
}

Use the stored state

This example opens a welcome or onboarding page the first time the app launches, then opens the normal waiting page on later launches:

import 'package:flutter_module/database/sqflite.dart';

final _sqlite = SqlLite();

await _sqlite.open();
print(await _sqlite.queryUserState());

List<Map<String, dynamic>> result = await _sqlite.queryUserState();
if (result[0]['code'] == 200) {
  if (result[0]['welComeTimes'] == 0) {
    _sqlite.insertUserState({
      "welComeTimes": result[0]['welComeTimes'] + 1
    });
    return Navigator.of(context).push(
      SlideInFromBottomRoute(Welcome())
    );
  } else {
    return Navigator.of(context).push(
      SlideInFromBottomRoute(Waiting())
    );
  }
}

The sample reflects an older null-safety era of Dart. Modern code should add explicit types, lifecycle handling, migrations, and database error handling.