Flutter: moor_flutter库,简化sqlite操作
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操作的更多相关文章
- [Android新手区] SQLite 操作详解--SQL语法
该文章完全摘自转自:北大青鸟[Android新手区] SQLite 操作详解--SQL语法 :http://home.bdqn.cn/thread-49363-1-1.html SQLite库可以解 ...
- Sqlite操作帮助类
sqlite帮助类 using System; using System.Collections.Generic; using System.Linq; using System.Text; us ...
- 基于Struts2框架实现登录案例 之 使用Struts2标签库简化表单+继承ActionSupport完成输入交验
一,使用Struts2标签库简化表单 在文章[基于Struts2框架实现登录案例]的基础上,通过使用Struts标签库可以简化登录页面login2.jsp <%@ page language=& ...
- 【小结】有关mysql扩展库和mysqli扩展库的crud操作封装
现阶段php如果要操作mysql数据库 php给我们提供了3套库 1.mysql扩展库 面向过程操作 2.mysqli扩展库 面向对象操作和面向过程操作并存 安全性和效率高于mysql扩展库 ...
- 在ASP.NET Core中使用AOP来简化缓存操作
前言 关于缓存的使用,相信大家都是熟悉的不能再熟悉了,简单来说就是下面一句话. 优先从缓存中取数据,缓存中取不到再去数据库中取,取到了在扔进缓存中去. 然后我们就会看到项目中有类似这样的代码了. pu ...
- 通过数组和枚举简化GPIO操作编码(转)
源: 通过数组和枚举简化GPIO操作编码
- 如何利用反射简化Servlet操作
如何利用反射简化Servlet操作 一.反射的实现 新建类BaseServlet,继承HttpServlet(不需要在web.xml文件中配置) 1.在doPost()方法中处理请求乱码,并调用d ...
- 封装CoreGraphics的API简化绘图操作
封装CoreGraphics的API简化绘图操作 效果 说明 1. 将CoreGraphics的API接口抽象为对象,让绘图变得简单易懂 2. 简化常用的绘制操作 3. 源码长期更新 源码 https ...
- php mysqli扩展库之预处理操作
分享下php使用mysqli扩展库进行预处理操作的二个例子,有意研究mysqli用法的朋友,可以参考学习下,一定会有所帮助的. 例1.使用mysqli扩展库的预处理技术 mysqli stmt 向数据 ...
随机推荐
- 作为一款内存数据库,为什么断电后Redis数据不会丢失
前言 Redis 作为一款内存数据库,被广泛使用于缓存,分布式锁等场景,那么假如断电或者因其他因素导致 Reids 服务宕机,在重启之后数据会丢失吗? Redis 持久化机制 Redis 虽然是定义为 ...
- Trie(字典树)
没时间整理了,老吕又讲课了@ @ 概念 Trie即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种,典型应用是统计和排序大量的字符串(不限于字符串) Trie字典树主要用于存储字符串, ...
- sql画图
---------------------------------------------------------------------------------------------------- ...
- Cisco交换机管理员配置
conf tservice timestamps debug datetime msec localtime yearservice timestamps log datetime msec loca ...
- Codeforces Round #653 (Div. 3)
比赛链接:https://codeforces.com/contest/1374 A. Required Remainder 题意 给出 $x, y, n$,找到最大的整数 $0 \le k \le ...
- zjnu1730 PIRAMIDA(字符串,模拟)
Description Sample Input 6 JANJETINA 5 1 J 1 A 6 N 6 I 5 E Sample Output 1 0 2 1 1 题意:给你一个长度小于等于10^6 ...
- python+selenium+bs4爬取百度文库内文字 && selenium 元素可以定位到,但是无法点击问题 && pycharm多行缩进、左移
先说一下可能用到的一些python知识 一.python中使用的是unicode编码, 而日常文本使用各类编码如:gbk utf-8 等等所以使用python进行文字读写操作时候经常会出现各种错误, ...
- Codeforces Round #682 (Div. 2) B. Valerii Against Everyone (思维)
题意:给你一组数\(b\),对于每个\(b_i\),相对应的\(a_i=2^{b_i}\),问你是否能找出两个不相交的区间,使得两个区间的\(a_i\)的元素和相等. 题解:对于任意一个\(2^k\) ...
- Codeforces Global Round 8 D. AND, OR and square sum (贪心,位运算)
题意:有\(n\)个数,选择某一对数使二者分别\(or\)和\(and\)得到两个新值,求操作后所有数平方和的最大值. 题解:不难发现每次操作后,两个数的二进制表示下的\(1\)的个数总是不变的,所以 ...
- CF1463-B. Find The Array
题意: 给出一个由n个数组成的数组a,这个数组的元素和为S,要求你找出一个由n个数字组成数组b,这个数组满足: 数组中的每个数可以将他两边的数字整除或者被他两边的数字整除 数组b中每个位置的数字减去数 ...