0

I need to list a table in a .db database. When I run the application in the emulator, the error "The getter 'length' was called on null" pops up for a second, but then the list I need is displayed immediately. And when you start Debug on a connected smartphone, everything stops with the error "The getter 'length' was called on null".

What could be the problem? It seems that somewhere there is not enough method of waiting for data from the database.

I/flutter (10923): /data/user/0/com.example.test_project/databases/database.db
I/flutter (10923): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY 
╞═══════════════════════════════════════════════════════════
I/flutter (10923): The following NoSuchMethodError was thrown building 
FutureBuilder<List<Authors>>(dirty, state:
I/flutter (10923): _FutureBuilderState<List<Authors>>#3ecfd):
I/flutter (10923): The getter 'length' was called on null.
I/flutter (10923): Receiver: null
I/flutter (10923): Tried calling: length

Database.dart

class DBProvider {
  DBProvider._();

  static final DBProvider db = DBProvider._();

  Database _database;

  Future<Database> get database async {

    _database = await initDB();
    return _database;
  }

  initDB() async {
    String path = join(await getDatabasesPath(), "database.db");
    var exists = await databaseExists(path);
    print(path);
    return await openDatabase(path);
  }

  Future<List<Authors>> getAllClients() async {
    final db = await database;
    var res = await db.query('category');
    print(res);
    List<Authors> list = [];
    list = res.map((c) => Authors.fromMap(c)).toList();
    return list;
  }
}

This is the class where the UI of the sheet of elements from the database is drawn.

class MainTab extends StatefulWidget {
  @override
  _MainTabState createState() => _MainTabState();
}

class _MainTabState extends State<MainTab> {

  @override
  Widget build(BuildContext context) {
      return Padding(
        padding: const EdgeInsets.only(left: 10, right: 10, bottom: 10),
        child: Container(
            padding: EdgeInsets.all(15),
            decoration: BoxDecoration(
                color: Theme.of(context).accentColor,
                borderRadius: BorderRadius.all(Radius.circular(30))
            ),
            child: FutureBuilder<List<Authors>>(
              future: DBProvider.db.getAllClients(),
              builder: (context, snapshot) {
                return ListView.builder(
                  itemCount: snapshot.data.length,
                  itemBuilder: (context, index) {
                    Authors item = snapshot.data[index];
                    return ListTile(
                      title: Text(item.name),
                      leading: Icon(Icons.folder),
                      trailing: Text(item.count.toString()),
                      onTap: () {

                      },
                    );
                  },
                );
              },
            )
        ),
      );
    }
}
Oleg Korotin
  • 3
  • 1
  • 2

1 Answers1

0

Use ConnectionState https://pub.dev/documentation/flutter_for_web/latest/widgets/FutureBuilder-class.html

You have to write something like this:

  FutureBuilder<List<Authors>>(
                future: DBProvider.db.getAllClients(),
                builder: (context, snapshot) {
                  switch (snapshot.connectionState) {
                    case ConnectionState.waiting:
                      return Center(
                        child: CircularProgressIndicator(),
                      );
                    case ConnectionState.done:
                      {
                        if (snapshot.hasError) {
                          return Center(
                        child: Text(snapshot.error.toString()),
                         );
                        } else if (snapshot.hasData) {
                           return ListView.builder(
                  itemCount:snapshot.data==null?0: snapshot.data.length,
                  itemBuilder: (context, index) {
                    Authors item = snapshot.data[index];
                    return ListTile(
                      title: Text(item.name),
                      leading: Icon(Icons.folder),
                      trailing: Text(item.count.toString()),
                      onTap: () {

                      },
                    );
                        }
                        return Center(child: Text('No Data'));
                      }
                    default:
                      return Container();
                  }
                }),


Jeltopuz
  • 51
  • 3
  • Now this error pops up on the screen: type 'SqfliteDatabaseException' is not a subtype of type 'String' – Oleg Korotin Apr 23 '20 at 09:23
  • I'm sorry, I didn’t notice. Writes an error: SQLITE_ERROR ... no such file or directory.But if I run Debug in the emulator, then it does not swear at the lack of a file. database.db is located in the assets / database.db folder. In pubspec.yaml also registered this file. – Oleg Korotin Apr 23 '20 at 09:30
  • https://stackoverflow.com/questions/51384175/sqlite-in-flutter-how-database-assets-work Try: Directory appDocDir = await getApplicationDocumentsDirectory(); String databasePath = join(appDocDir.path, 'asset_database.db'); this.db = await openDatabase(databasePath); initialized = true; – Jeltopuz Apr 23 '20 at 09:37
  • Or var exists = await databaseExists(path); return true? – Jeltopuz Apr 23 '20 at 09:41
  • Сейчас и в эмуляторе такая же ошибка "No such file or firectory" – Oleg Korotin Apr 23 '20 at 10:06