sqlite - 使用flutter的sqflite报错database_closed

标签 sqlite flutter dart sqflite database-caching

我尝试使用 sqflite 来保存一些数据,比如我的类电影,但是当我尝试插入或查询数据库时,看到这条消息:

[ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: DatabaseException(error database_closed)

我的 MovieBloc 类:

List<Movie> _movies = new List<Movie> ();
class MoviesBloc implements BaseBloc {
  final  _moviesController = StreamController<List<Movie>>();
  Database moviesDB;
  String _moviesPath;
  Stream<List<Movie>> get moviesStream => _moviesController.stream;
  List<Movie> get movies => _movies;

  int getLengthMovieList() {
    return _movies.length;
  }
  clearMovieList() {
    _movies.clear();
  }

  Future<void> openMovieDB({String dbName:'movies.db'}) async {

    var databasesPath = await getDatabasesPath();
    _moviesPath = join(databasesPath, dbName);

    moviesDB = await openDatabase(_moviesPath, version: 1,
        onCreate: (Database db, int version) async {
          await db.execute(
              'CREATE TABLE movies (Id INTEGER PRIMARY KEY AUTOINCREMENT, Title TEXT NOT NULL, imdbRating TEXT, Poster TEXT, Plot TEXT, Saved INTEGER DEFAULT 0)');
        });
  }
  Future<void> closeMovieDB() async => moviesDB.close();

  void dispose() {
    _moviesController.close();
  }
}

我的 MovieProvider 类:

class MovieProvider extends MoviesBloc {
  String _tableName = 'movies';

  Future<Movie> insert(Movie movie, {conflictAlgorithm: ConflictAlgorithm.ignore}) async {
    await moviesDB.insert(_tableName, movie.toMap(), conflictAlgorithm: conflictAlgorithm);
    return movie;
  }

  Future<bool> insertAll(List<Movie> movies) async {
    await Future.wait(movies.map((movie) async {
      await this.insert(movie);
    }
    ));
    return true;
  }

  Future<List<Movie>> paginate(int page, {int limit: 15}) async {
    print('in Paginate to SQLite');
    List<Map> maps  = await moviesDB.query(_tableName,
        columns: ['Id', 'Title', 'imdbRating', 'Poster', 'Plot', 'Saved'],
        limit: limit,
        offset: page == 1 ? 0 : ((page -1) * limit)
    );
    List<Movie> movies = new List<Movie> ();
      if (maps.length > 0) {
        maps.map((movie) {
          movies.add(Movie.fromJson(movie));
        }
        );
      }
    return movies;
  }
}

我的 save 方法到 sqflite:

static Future<bool> saveAllMoviesIntoSqlite(List<Movie> movies) async {
    var db = new MovieProvider();
    await db.openMovieDB();
    await db.insertAll(movies);
    await db.closeMovieDB();
    return true;
  }

我的 load 方法来自 sqflite:

 static Future<Map> getAllMoviesFromSqlite(int page) async {
    var db = new MovieProvider();
    await db.openMovieDB();
    List<Movie> movies = new List<Movie> ();
    movies = await db.paginate(page);
    await db.closeMovieDB();
    return {
      "currentPage": page,
      "movies": movies
    };
  }

  • 我观察到,在 MovieProvider 类的 insertAll 方法中,使用 await 和 async 将 movies 列表中的任何电影插入到 sq:<
 Future<bool> insertAll(List<Movie> movies) async {
    await Future.wait(movies.map((movie) async {
      await this.insert(movie);
    }
    ));
    return true;
  }
  • 我尝试关闭打开数据库,有时顺序和其他播放关闭打开数据库.. .

我的日志:

I/flutter ( 1617): in Paginate to SQLite
E/flutter ( 1617): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: DatabaseException(error database_closed)
E/flutter ( 1617): #0      SqfliteDatabaseMixin.checkNotClosed (package:sqflite_common/src/database_mixin.dart:282:7)
E/flutter ( 1617): #1      SqfliteDatabaseExecutorMixin._rawQuery (package:sqflite_common/src/database_mixin.dart:125:8)
E/flutter ( 1617): #2      SqfliteDatabaseExecutorMixin.query (package:sqflite_common/src/database_mixin.dart:110:12)
E/flutter ( 1617): #3      MovieProvider.paginate (package:umdb/bloc/movie_provider.dart:24:38)
E/flutter ( 1617): #4      MovieService.getAllMoviesFromSqlite (package:umdb/services/movie_service.dart:54:23)
E/flutter ( 1617): <asynchronous suspension>
E/flutter ( 1617): #5      MovieService.getSavedFromSQ (package:umdb/services/movie_service.dart:95:26)
E/flutter ( 1617): #6      MovieService.fetchSavedMovies (package:umdb/services/movie_service.dart:105:5)
E/flutter ( 1617): <asynchronous suspension>
E/flutter ( 1617): #7      MovieDetailState.build.<anonymous closure>.<anonymous closure> (package:umdb/ui_widgets/movie_detail.dart:168:42)
E/flutter ( 1617): #8      State.setState (package:flutter/src/widgets/framework.dart:1240:30)
E/flutter ( 1617): #9      MovieDetailState.build.<anonymous closure> (package:umdb/ui_widgets/movie_detail.dart:142:27)
E/flutter ( 1617): #10     GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:184:24)
E/flutter ( 1617): #11     TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:524:11)
E/flutter ( 1617): #12     BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:284:5)
E/flutter ( 1617): #13     BaseTapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:256:7)
E/flutter ( 1617): #14     GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:158:27)
E/flutter ( 1617): #15     GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:224:20)
E/flutter ( 1617): #16     GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:200:22)
E/flutter ( 1617): #17     GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:158:7)
E/flutter ( 1617): #18     GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:104:7)
E/flutter ( 1617): #19     GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:88:7)
E/flutter ( 1617): #20     _rootRunUnary (dart:async/zone.dart:1206:13)
E/flutter ( 1617): #21     _CustomZone.runUnary (dart:async/zone.dart:1100:19)
E/flutter ( 1617): #22     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
E/flutter ( 1617): #23     _invoke1 (dart:ui/hooks.dart:267:10)
E/flutter ( 1617): #24     _dispatchPointerDataPacket (dart:ui/hooks.dart:176:5)

请帮我解决一下

最佳答案

处理打开/关闭数据库非常困难。在很多情况下,您可能会访问一个已关闭的数据库,更糟糕的是,如果您打开同一个数据库两次,您将获得相同的实例,因此第一次关闭将关闭该数据库。

我个人建议保持数据库打开。

如果您需要处理多个数据库并为短操作打开/关闭它们,请确保您有适当的互斥锁/锁定机制,以便您可以控制打开/访问/关闭数据库的方式,而无需任何其他方法尝试访问同时使用相同的数据库(好的,那部分不清楚抱歉)。

类似的东西(虽然我真的不建议每次都打开/关闭):

import 'package:synchronized/synchronized.dart';

final static _lock = Lock();

static Future<bool> saveAllMoviesIntoSqlite(List<Movie> movies) async {
  return _lock.synchronized(() {
    var db = new MovieProvider();
    await db.openMovieDB();
    await db.insertAll(movies);
    await db.closeMovieDB();
    return true;
  });
}

static Future<Map> getAllMoviesFromSqlite(int page) async {
  return _lock.synchronized(() {
    var db = new MovieProvider();
    await db.openMovieDB();
    List<Movie> movies = new List<Movie> ();
    movies = await db.paginate(page);
    await db.closeMovieDB();
    return {
      "currentPage": page,
      "movies": movies
    };
  });
}

关于sqlite - 使用flutter的sqflite报错database_closed,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63812832/

相关文章:

java - com.sun.istack.internal.SAXException2 : unable to marshal type as an element

flutter - 当 AppLifeCycleState.detached 被调用时?

mobile - Dart - 生成多个隔离时在控制台中获取 'Malformed message'

javascript - 粘贴到 Canvas 中

SQL 按一列分组,计算另一列中的条目

ios - NSDate 和 SQLite3

c# - 如何使用 DbLinq 和 SQLite 进行左外连接?

flutter - 当我使用NotificationListener时,RefreshIndicator在flutter中不起作用

android - 将 flutter 从 2.5 升级到 2.8 后出错

intellij-idea - Alt+Enter 停止在 IntelliJ 中处理 Dart 文件