install

dependencies:
...
moor_flutter: dev_dependencies:
...
moor_generator:
build_runner:

lib\db\moor.db.dart

import 'package:moor_flutter/moor_flutter.dart';

part 'moor.db.g.dart';

// 建表
class Tasks extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get name => text().withLength(min: 1, max: 50)();
DateTimeColumn get dueData => dateTime().nullable()();
BoolColumn get completed => boolean().withDefault(const Constant(false))();
} @UseMoor(tables: [Tasks])
class AppDatabase extends _$AppDatabase {
AppDatabase()
: super(FlutterQueryExecutor.inDatabaseFolder(path: 'db.sqlite'));
@override
int get schemaVersion => 1; Future<List<Task>> get getAllTasks => select(tasks).get(); /// 每当基础数据发生变化时,都会发出新项
Stream<List<Task>> watchAllTasks() => select(tasks).watch(); /// 插入一条数据
Future<int> insertTask({
String name,
DateTime dueData,
}) =>
into(tasks).insert(
TasksCompanion(
name: Value(name),
dueData: Value(dueData),
),
); /// 更新一条数据
Future<bool> updateTask(Task task) => update(tasks).replace(task); /// 删除一条数据
Future<int> deleteTask(Task task) => delete(tasks).delete(task);
}

lib\store\main\main.store.dart

import 'package:flutter_moor_demo/db/moor.db.dart';

class MainStore {
final dbService = DBService();
} class DBService {
final database = AppDatabase();
Stream<List<Task>> get tasks$ =>
database.watchAllTasks().map((List<Task> tasks) {
/// 排序,把完成的排在后面
tasks.sort(
(a, b) => _getInt(a.completed).compareTo(_getInt(b.completed)),
);
return tasks;
});
int _getInt(bool b) {
return b ? 1 : 0;
}
} final MainStore mainStore = MainStore();

lib\main.dart

import 'package:flutter/material.dart';
import 'package:flutter_moor_demo/store/main/main.store.dart'; import 'db/moor.db.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
} class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
} class _HomePageState extends State<HomePage> {
DateTime newTaskDate;
TextEditingController controller;
@override
void initState() {
super.initState();
controller = TextEditingController();
} @override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Tasks'),
),
body: Column(
children: <Widget>[
Expanded(
child: StreamBuilder<List<Task>>(
stream: mainStore.dbService.tasks$,
initialData: List<Task>(),
builder: (context, snap) {
if (snap.connectionState == ConnectionState.active) {
List<Task> tasks = snap.data;
if (tasks.isEmpty) return Center(child: Text('Not Data'));
return ListView.builder(
itemCount: tasks.length + 1,
itemBuilder: (context, int index) {
if (index == 0) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Center(child: Text('taskS #${tasks.length}')),
);
}
final task = tasks[index - 1];
return Dismissible(
key: ValueKey(task.id),
background: Container(color: Colors.red),
onDismissed: (DismissDirection d) {
mainStore.dbService.database.deleteTask(task);
},
child: CheckboxListTile(
title: Text(task.name),
subtitle: Text(task.dueData?.toString() ?? 'No date'),
value: task.completed,
onChanged: (bool nv) {
mainStore.dbService.database
.updateTask(task.copyWith(completed: nv));
},
),
);
},
);
} else if (snap.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else {
return SizedBox();
}
},
),
),
ListTile(
title: TextField(
controller: controller,
decoration: InputDecoration(hintText: 'Task Name'),
onSubmitted: (String v) {
mainStore.dbService.database.insertTask(
name: v.trim(),
dueData: newTaskDate,
); _reset();
},
),
trailing: IconButton(
icon: Icon(Icons.calendar_today),
onPressed: () async {
DateTime now = DateTime.now();
Duration d = Duration(days: 10);
newTaskDate = await showDatePicker(
context: context,
initialDate: now,
firstDate: now.subtract(d),
lastDate: now.add(d));
},
),
)
],
),
);
} void _reset() {
setState(() {
controller.clear();
newTaskDate = null;
});
}
}

moor_flutter迁移至moor_ffi

import 'dart:io';

import 'package:moor/moor.dart';
import 'package:moor_ffi/moor_ffi.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as p; part 'tabel.g.dart'; // 这将为我们生成一个名为todos的表。 该表的行将
// 由称为Todo的类表示
class Todos extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get title => text().withLength(min: 6, max: 32)();
TextColumn get content => text().named('body')();
IntColumn get category => integer().nullable()();
} // 这将使moor生成一个名为"Category"的类来表示该表中的一行。
// 在表格名称中,默认情况下,将使用"Categorie",因为它只会去除结尾的"s"
@DataClassName("Category")
class Categories extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get description => text()();
} LazyDatabase _openConnection() {
// LazyDatabase实用程序使我们能够找到文件异步的正确位置。
return LazyDatabase(() async {
// 将数据库文件db.sqlite放入documents文件夹
// 为您的应用.
final dbFolder = await getApplicationDocumentsDirectory();
final file = File(p.join(dbFolder.path, 'db.sqlite'));
return VmDatabase(file);
});
} // 此注释告诉moor准备使用两个
// 我们刚刚定义的表格。 稍后我们将介绍如何使用该数据库类
@UseMoor(tables: [Todos, Categories])
class MyDatabase extends _$MyDatabase {
// 我们通过这个构造函数告诉数据库在哪里存储数据
MyDatabase() : super(_openConnection()); // 您应该在更改或添加表定义时增加该数字
// 本自述文件稍后将介绍迁移
@override
int get schemaVersion => 1; Stream<List<Todo>> allTodos() {
return (select(todos)).watch();
} Future<int> add(Insertable<Todo> d) {
return into(todos).insert(d);
}
}

使用

import 'package:flutter/material.dart';
import 'package:flutter_demo/db/tabel.dart'; MyDatabase db;
void main() {
db = MyDatabase();
runApp(MyApp());
} class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
} class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
} class _HomePageState extends State<HomePage> {
int _id = 1;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home Page'),
),
body: StreamBuilder<List<Todo>>(
stream: db.allTodos(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting ||
!snapshot.hasData) return SizedBox();
return ListView(
children: snapshot.data.map((it) {
// 这里表的字段和上面定义的不一样
return ListTile(
key: ValueKey(it.id),
title: Text(it.title),
subtitle: Text(it.content),
);
}).toList(),
);
},
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
setState(() {
_id++;
});
// 插入新数据
var newTodo = TodosCompanion.insert(
title: '#$_id new title', content: '#$_id content');
db.add(newTodo);
},
),
);
}
}

Flutter: moor_flutter库,简化sqlite操作的更多相关文章

  1. [Android新手区] SQLite 操作详解--SQL语法

    该文章完全摘自转自:北大青鸟[Android新手区] SQLite 操作详解--SQL语法  :http://home.bdqn.cn/thread-49363-1-1.html SQLite库可以解 ...

  2. Sqlite操作帮助类

      sqlite帮助类 using System; using System.Collections.Generic; using System.Linq; using System.Text; us ...

  3. 基于Struts2框架实现登录案例 之 使用Struts2标签库简化表单+继承ActionSupport完成输入交验

    一,使用Struts2标签库简化表单 在文章[基于Struts2框架实现登录案例]的基础上,通过使用Struts标签库可以简化登录页面login2.jsp <%@ page language=& ...

  4. 【小结】有关mysql扩展库和mysqli扩展库的crud操作封装

    现阶段php如果要操作mysql数据库 php给我们提供了3套库 1.mysql扩展库   面向过程操作 2.mysqli扩展库  面向对象操作和面向过程操作并存  安全性和效率高于mysql扩展库 ...

  5. 在ASP.NET Core中使用AOP来简化缓存操作

    前言 关于缓存的使用,相信大家都是熟悉的不能再熟悉了,简单来说就是下面一句话. 优先从缓存中取数据,缓存中取不到再去数据库中取,取到了在扔进缓存中去. 然后我们就会看到项目中有类似这样的代码了. pu ...

  6. 通过数组和枚举简化GPIO操作编码(转)

    源: 通过数组和枚举简化GPIO操作编码

  7. 如何利用反射简化Servlet操作

    如何利用反射简化Servlet操作   一.反射的实现 新建类BaseServlet,继承HttpServlet(不需要在web.xml文件中配置) 1.在doPost()方法中处理请求乱码,并调用d ...

  8. 封装CoreGraphics的API简化绘图操作

    封装CoreGraphics的API简化绘图操作 效果 说明 1. 将CoreGraphics的API接口抽象为对象,让绘图变得简单易懂 2. 简化常用的绘制操作 3. 源码长期更新 源码 https ...

  9. php mysqli扩展库之预处理操作

    分享下php使用mysqli扩展库进行预处理操作的二个例子,有意研究mysqli用法的朋友,可以参考学习下,一定会有所帮助的. 例1.使用mysqli扩展库的预处理技术 mysqli stmt 向数据 ...

随机推荐

  1. P4826

    总的来说, 这道题只考查了单纯的建图和最大生成树 但这却是蓝题(问号 题意 题意的理解比较麻烦 简单说就是 n 支队伍比赛,i 号队伍和 j 号队伍比赛可获得 i ^ j 的分数,然后其中一支队伍会输 ...

  2. SpringMVC 通过commons-fileupload实现文件上传

    目录 配置 web.xml SpringMVC配置文件 applicationContext.xml 文件上传 Controller 上传实现一 上传实现二 测试 依赖 配置 web.xml < ...

  3. 用于理解Java的前8个图表

    尤其记得高中上数学课的时候,数学老师课堂上最喜欢说的一句话:"数形结合百般好":这些年过去,数学虽然学的并未多么好,但这句话倒是一直烙印在我的脑海,在其他学科的学习当中,我总是尽量 ...

  4. JS 实现一个实时动态校验,将输入格式错误的显示为红色背景

    功能描述: 源码: 功能描述: 实时动态校验,如果输入的格式错误,将弹窗提示输入格式错误并将背景展示为红色. 源码: 前台: <hy:formfield name="cxfdl&quo ...

  5. spark SQL (四)数据源 Data Source----Parquet 文件的读取与加载

    spark SQL Parquet 文件的读取与加载 是由许多其他数据处理系统支持的柱状格式.Spark SQL支持阅读和编写自动保留原始数据模式的Parquet文件.在编写Parquet文件时,出于 ...

  6. linux环境变量 shell变量 command not found解决方法(转)

    在Ubuntu.centos中有如下几个文件可以设置环境变量1./etc/profile:在登录时,操作系统定制用户环境时使用的第一个文件,此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文 ...

  7. Kubernetes --(k8s)volume 数据管理

    容器的磁盘的生命周期是短暂的,这就带来了许多问题:第一:当一个容器损坏了,kubelet会重启这个容器,但是数据会随着container的死亡而丢失:第二:当很多容器在同一Pod中运行的时候,经常需要 ...

  8. 小白搭建WNMP详细教程---NGINX安装与设置

    一.Nginx下载 Nginx (engine x) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器.Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Ramble ...

  9. 黑客练手入门| pwnable.kr—幼儿瓶—01:fd

    目录 前言 pwnable.kr介绍 该怎么玩 幼儿瓶第一道题:fd 0x00 问题描述 0x01 源码分析 0x02 解题方法 0x03 知识点总结 前言 担心有人不知道pwnable.kr是什么, ...

  10. 回文树(回文自动机PAM)小结

    回文树学习博客:lwfcgz    poursoul 边写边更新,大概会把回文树总结在一个博客里吧... 回文树的功能 假设我们有一个串S,S下标从0开始,则回文树能做到如下几点: 1.求串S前缀0~ ...