【Flutter -- 进阶】sqflite 数据库

【Flutter -- 进阶】sqflite 数据库_第1张图片

文章目录

    • 1. 前言
    • 2. 创建数据库和数据表
    • 3. 增加数据
    • 4. 查询具体数据
    • 5. 删除数据
    • 6. 修改数据
    • 7. 查询条数

1. 前言

Android 和 iOS 中都会有 SQLite,那么 Flutter 有没有呢?答案是肯定有的。Flutter 中的 SQLite 数据库是同时支持 Android 和 iOS 的,它的名字叫 sqflite ,支持事务和批量操作,支持插入/查询/更新/删除操作等,是轻量级的关系型数据库。

下面先简单实现一个登录界面,进行简单的数据操作:

//用无状态控件显示
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      //主题色
      theme: ThemeData(
          //设置为蓝色
          primarySwatch: Colors.red),
      //这是一个Widget对象,用来定义当前应用打开的时候,所显示的界面
      home: DataBaseWidget(),
    );
  }
}

//主框架
class DataBaseWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new _DataBaseState();
  }
}

class _DataBaseState extends State<DataBaseWidget> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      //appBar
      appBar: AppBar(
        title: Text("Sqlite简单操作"),
        //标题居中
        centerTitle: true,
      ),
      body: new ListView(
        children: <Widget>[
          //用户输入用户信息widget
          Padding(
            padding: const EdgeInsets.only(left: 16, right: 16),
            child: InputMessageWidget(),
          ),
          //数据库表的一些基本操作,增,删,改,查
          Padding(
            padding: const EdgeInsets.all(16),
            child: SqliteHandleWidget(),
          ),
        ],
      ),
    );
  }
}

用户输入信息的 Widget 组件:

//用户名和密码
class InputMessageWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //这个是为了用户输入结束后,让密码输入框获取到焦点
    FocusNode secondTextFieldNode = FocusNode();
    return Column(
      children: <Widget>[
        TextField(
          //文字内容改变触发
          onChanged: (user) {
            //获取用户名
            username = user;
          },
          //输入法装饰器
          decoration: InputDecoration(
              //标签
              labelText: '名字',
              //hint 提示用户输入什么
              hintText: '请输入英文或者数字'),
          //最大为一行
          maxLines: 1,
          //文字提交触发
          onSubmitted: (result) {
            FocusScope.of(context).reparentIfNeeded(secondTextFieldNode);
          },
        ),
        TextField(
          onChanged: (pwd) {
            //获取用户密码
            password = pwd;
          },
          //是否隐藏输入 false 表示不隐藏,true表示隐藏
          obscureText: true,
          maxLines: 1,
          decoration: InputDecoration(
            labelText: '密码',
            hintText: '请输入密码',
          ),
          //键盘输入类型
          keyboardType: TextInputType.text,
          onSubmitted: (data) {},
        ),
      ],
    );
  }
}

对数据库表操作的按钮布局如下:

//数据库组件操作
class SqliteHandleWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new _SqliteHandleWidgetState();
  }
}

class _SqliteHandleWidgetState extends State<SqliteHandleWidget> {
  //数据库名称
  String myDataBase = "usermessage.db";

  //数据库路径
  String myDataBasePath = "";

  //数据库中的表 简单一点,就创建三个字段,分别是主键,用户名,密码
  String sql_createUserTable = "CREATE TABLE user("
      "id INTEGER PRIMARY KEY,"
      "username TEXT,"
      "password TEXT)";

  //查找数据库表的数目
  String sql_queryCount = 'SELECT COUNT(*) FROM user';

  //具体查找数据库表的所有信息
  String sql_queryMessage = 'SELECT * FROM user';

  //这是从数据库表返回数据
  var _data;

  @override
  Widget build(BuildContext context) {
    return Column(
      //交叉轴设置中间
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        Container(
          height: 40.0,
          child: RaisedButton(
            textColor: Colors.black,
            child: Text("创建数据库表"),
            onPressed: null,
          ),
        ),
          Row(
            //主轴方向中心对齐
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              new RaisedButton(
                  textColor: Colors.black,
                  child: new Text('增'),
                  onPressed: null),
              new RaisedButton(
                  textColor: Colors.black,
                  child: new Text('删'),
                  onPressed: null),
              new RaisedButton(
                  textColor: Colors.black,
                  child: new Text('改'),
                  onPressed: null),
            ],
        ),
        Row(
          //主轴方向中心对齐
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new RaisedButton(
                textColor: Colors.black,
                child: new Text('查条数'),
                onPressed: null),
            new RaisedButton(
                textColor: Colors.black,
                child: new Text('查信息'),
                onPressed: null),
          ],
        ),
        Padding(
          padding: const EdgeInsets.all(16.0),
          child: new Text('具体结果是:$_data'),
        ),
      ],
    );
  }
}

在上面_SqliteHandleWidgetState赋值数据库名字为usermessage.db,创建数据库表user语句很简单,就三个字段,分别是主键,用户名,用户密码,界面如下:
【Flutter -- 进阶】sqflite 数据库_第2张图片

2. 创建数据库和数据表

首先在 pubspec.xml 文件添加依赖:可以到 Dart 包管理网站去查找 sqlite 依赖最新版本。

  sqflite: ^1.1.0

并在文件引入:

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

注意:对于数据库的操作都是耗时操作,都要通过异步来处理。

  //创建数据库
  Future<String> createDataBase(String db_name) async {
    //在文档目录建立
    var document = await getApplicationDocumentsDirectory();
    //获取路径 join是path包下的方法,就是将两者路径连接起来
    String path = join(document.path, db_name);
    //逻辑是如果数据库存在就把它删除然后创建
    var _directory = new Directory(dirname(path));
    bool exists = await _directory.exists();
    if (exists) {
      //必存在 这里是为了每次创建数据库表先表删除则删除数据库表
      await deleteDatabase(path);
    } else {
      try {
        //不存在则创建目录  如果[recursive]为false,则只有路径中的最后一个目录是
        //创建。如果[recursive]为真,则所有不存在的路径
        //被创建。如果目录已经存在,则不执行任何操作。
        await new Directory(dirname(path)).create(recursive: true);
      } catch (e) {
        print(e);
      }
    }
    return path;
  }


  //创建数据库表方法
  cratedb_table() async {
    //得到数据库的路径
    myDataBasePath = await createDataBase(myDataBase);
    //打开数据库
    Database my_db = await openDatabase(myDataBasePath);
    //创建数据库表
    await my_db.execute(sql_createUserTable);
    //关闭数据库
    await my_db.close();
    setState(() {
      _data = "创建usermessage.db成功,创建user表成功~";
    });
}

给按钮添加点击方法:

          child: RaisedButton(
            textColor: Colors.black,
            child: Text("创建数据库表"),
            onPressed: cratedb_table,
          ),

运行,安装完apk,用Device File Exploder来看看内部存储文件:
【Flutter -- 进阶】sqflite 数据库_第3张图片
下面点击创建数据库,后synchronize来刷新一下:
【Flutter -- 进阶】sqflite 数据库_第4张图片
发现在 app_flutter下多了usermessage.db 文件,确实数据库创建成功了,那继续下面的操作。

3. 增加数据

下面实现增加数据,可以用rawInsert或者db.insert方式对数据库表数据进行增加(插入),实际上都是通过insert into方式来插入数据表,下面就用rawInsert方式来增加一条数据:

//增加方法
addData() async {
    //首先打开数据库
    Database my_db = await openDatabase(myDataBasePath);
    //插入数据
    String add_sql = "INSERT INTO user(username,password) VALUES('$username','$password')";
    await my_db.transaction((tran) async{
       await tran.rawInsert(add_sql);
    });
    //关闭数据库
    await my_db.close();
    setState(() {
      _data = "增加一条数据成功,名字是:$username,密码是:$password";
    });
}

4. 查询具体数据

为了配合增加数据,把查询数据库表的功能实现:

//查询具体数值
queryDetail() async{
    //打开数据库
    Database  my_db = await openDatabase(myDataBasePath);
    //将数据放到集合里面显示
    List<Map> dataList = await my_db.rawQuery(sql_queryMessage);
    await my_db.close();
    setState(() {
       _data = "具体数据详情如下:$dataList";
    });
}

查询数据表很简单,实际上只用rawQuery这个方法,把增加和查询方法绑定到按钮点击上:

new RaisedButton(
    textColor: Colors.black, child: new Text('改'), onPressed: null),
....
new RaisedButton(
    textColor: Colors.black,
    child: new Text('查信息'),
    onPressed: queryDetail),

验证结果,流程是:

  1. 先输入用户名和密码
  2. 点击增加
  3. 点击查信息

运行结果如下:
【Flutter -- 进阶】sqflite 数据库_第5张图片

5. 删除数据

下面实现删除数据:

//删除一条数据
delete() async {
    Database my_db = await openDatabase(myDataBasePath);
    //根据id来删除 也可以根据其他信息来删除 例如名字
    String delete_ssql = "DELETE FROM user WHERE id = ?";
    //返回所更改的数目
    int delete_count = await my_db.rawDelete(delete_ssql,['1']);
    //关闭数据库
    await my_db.close();
    //状态更新
    setState(() {
      if(delete_count == 1){
         _data = "删除成功~";
      } else {
        _data = "删除失败,请看错误日志~";
      }
    });
}

6. 修改数据

修改数据我相信在平时开发中是用的最频繁的操作了,直接上实现例子:

//修改数据方法
update() async{
   //数据库
   Database my_db = await openDatabase(myDataBasePath);
   String update_sql = "UPDATE user SET username = ? WHERE id = ?";
   await my_db.rawUpdate(update_sql,['paul','1']);
   await my_db.close();

   setState(() {
      _data = "数据修改成功,请查阅~";
   });

}

上面用了rawUpdate对数据库表进行内容数据更新,也可以用db.update来更新,自己可以根据需求变更去修改固定字段或者整条数据。上面我是根据 id 这个条件来修改一条数据,将 id 为 1 的数据的名字改为paul

7. 查询条数

//查询有几条
query_num() async{
  //数据库
  Database my_db = await openDatabase(myDataBasePath);
  //用sqflite包的方法firstInValue
  int data_count = Sqflite.firstIntValue(await my_db.rawQuery(sql_queryCount));
  await my_db.close();
  setState(() {
    _data = "数据条数:$data_count";
  });
}

你可能感兴趣的:(Flutter,--,实战,flutter,android)