美文网首页Flutter
六、Flutter之数据库

六、Flutter之数据库

作者: 夏_Leon | 来源:发表于2019-02-28 20:01 被阅读37次

    Flutter中操作数据库可以通过sqflite来实现,支持事务和批量操作,支持在Android、iOS后台线程执行任务,详见文档 https://pub.dartlang.org/packages/sqflite
    另外可参考 https://www.jianshu.com/p/7ac3ce2bc0c6
    对应的demo地址 https://github.com/zhujian1989/flutter_study/blob/master/lib/widget/demo_database/data_page.dart
    本文代码参考上面demo作了一些调整。

    1、添加依赖

    在demo中会用到路径等多个插件库,一并加载
    在pubspec.yaml添加

    dependencies:
      flutter:
        sdk: flutter
    
      # The following adds the Cupertino Icons font to your application.
      # Use with the CupertinoIcons class for iOS style icons.
      cupertino_icons: ^0.1.2
      event_bus: ^1.0.1
      sqflite: ^1.1.0
      shared_preferences: ^0.5.1
      path_provider: ^0.5.0
    

    dart文件中导入包

    import 'package:flutter/material.dart';
    import 'package:sqflite/sqflite.dart';
    import 'package:shared_preferences/shared_preferences.dart';
    import 'package:path_provider/path_provider.dart';
    import 'package:path/path.dart';
    import 'dart:io';
    

    2、数据库的创建、打开

      //创建数据库
      Future<String> _createNewDb(String dbName) async {
        //获取数据库文件路径
        var dbPath = await getDatabasesPath();
        print('dbPath:' + dbPath);
    
        String path = join(dbPath, dbName);
    
        if (await new Directory(dirname(path)).exists()) {
          await deleteDatabase(path);
        } else {
          try {
            await new Directory(dirname(path)).create(recursive: true);
          } catch (e) {
            print(e);
          }
        }
        return path;
      }
    
      _create() async {
        dbPath = await _createNewDb(dbName);
        Database db = await openDatabase(dbPath);
    
        await db.execute(sql_createTable);
        await db.close();
        setState(() {
          _result = '创建user.db成功,创建user_table成功';
        });
      }
    
      //打开数据库,获取数据库对象
      _open() async {
        if(null == dbPath){
          var path = await getDatabasesPath();
          dbPath = join(path, dbName);
          print('dbPath:' + dbPath);
        }
        return await openDatabase(dbPath);
      }
    

    数据库的创建、打开,都需要先获取数据库文件的路径,获取到path之后Database db = await openDatabase(dbPath);获取数据库对象,注意数据库的操作全都是异步的,要用关键字await。

    3、数据库的增删改查

      _add() async {
        Database db = await _open();
    
        String sql =
            "INSERT INTO user_table(username,pwd) VALUES('$username','$pwd')";
        //开启事务
        await db.transaction((txn) async {
          int id = await txn.rawInsert(sql);
        });
        await db.close();
    
        setState(() {
          _result = "插入username=$username,pwd=$pwd数据成功";
        });
      }
    
      _delete() async {
        Database db = await _open();
    
        //删除最近一条
        String sql = "DELETE FROM user_table where id in (select id from user_table order by id desc limit 1)";
        int count = await db.rawDelete(sql);
    
        await db.close();
    
        setState(() {
          if (count == 1) {
            _result = "删除成功,请查看";
          } else {
            _result = "删除0条数据或删除失败,请看log";
          }
        });
      }
    
      _update() async {
        Database db = await _open();
        String sql = "UPDATE user_table SET pwd = ? WHERE id = ?";
        int count = await db.rawUpdate(sql, ["654321", '1']);
        print(count);
        await db.close();
        setState(() {
          _result = "更新数据成功,请查看";
        });
      }
    
      //批量增、改、删数据
      _batch() async {
        Database db = await _open();
        var batch = db.batch();
        batch.insert("user_table", {"username": "batchName1"});
        batch.update("user_table", {"username": "batchName2"}, where: "username = ?",whereArgs: ["batchName1"]);
        batch.delete("user_table", where: "username = ?", whereArgs: ["Leon"]);
        //返回每个数据库操作的结果组成的数组 [6, 3, 0]:新增返回id=6,修改了3条数据,删除了0条数据
        var results = await batch.commit();
        await db.close();
        setState(() {
          _result = "批量增、改数据成功 "+results.toString();
        });
    
      }
    
      _queryNum() async {
        Database db = await _open();
        int count = Sqflite.firstIntValue(await db.rawQuery(sql_query_count));
        await db.close();
        setState(() {
          _result = "数据条数:$count";
        });
      }
    
      _query() async {
        Database db = await _open();
        List<Map> list = await db.rawQuery(sql_query);
        await db.close();
        setState(() {
          _result = "数据详情:$list";
        });
      }
    

    上面的增加数据代码中开启了事务,可以进行批量插入,每次数据库操作结束都要记得关闭await db.close();
    注意,当使用transaction对象访问数据时,不能再使用database对象访问数据库

    await database.transaction((txn) async {
      await txn.execute("CREATE TABLE Test1 (id INTEGER PRIMARY KEY)");
    
      // 不能在transaction对象里面使用database对象,这会发生死锁
      // await database.execute("CREATE TABLE Test2 (id INTEGER PRIMARY KEY)");
    });
    
    

    支持批量操作,但是真正操作被执行是在事务被提交的时候,比如上面代码中的var results = await batch.commit();

    后续待补充...

    相关文章

      网友评论

        本文标题:六、Flutter之数据库

        本文链接:https://www.haomeiwen.com/subject/oskfuqtx.html