1. 前言
Flutter官方对两种数据库更加推荐,且为它们提供了更好的支持,分别是
SQLite:一种本地数据库,优点顾名思义,更加轻量化,且对移动设备的支持更好;缺点是无法云上部署并通过IP链接
FireBase:由Google官方提供的NoSQL数据库,向用户提供了非常丰富的API接口,且为多用户聊天提供了很好的原生支持,是制作聊天功能的首选
这里仍然选择MySQL的原因:
- 没学过数据库,用老牌数据库学一下常规操作先
- 可以云上部署,在自己的服务器上部署特别方便
- 在腾讯云服务器上部署规避Google科学上网的限制
2. MySQL 安装 简单配置
Ubuntu 服务器
打开终端用ssh命令行安装还是太麻烦了
直接用宝塔的数据库功能,点添加数据库,填写config就好
更细致的操作,如创建用户、编辑权限、创建表等,点击phpMyAdmin进入php管理页面操作
Windows
在MySQL官网下载安装包后安装
SQL 可视化管理工具
推荐DBeaver,官网下载安装即可
配置简单,界面直观,功能丰富
可以管理云端数据库
支持多种SQL
常用命令
启动:net start mysql
尽量用管理员权限
关闭:net stop mysql
本地链接 mysql -u your_username -p
root用户可能不用输入密码
列出所有数据库 SHOW DATABASES;
选择要使用的数据库(进入数据库) USE your_database;
列出此数据库中的所有表 SHOW TABLES;
创建数据库 CREATE DATABASE 数据库名;
创建数据表
CREATE TABLE table_name (
column1 datatype,
column2 datatype,
...
);
插入数据
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);
3. Flutter链接MySQL
在pub.dev中,有三种第三方编写的MySQL插件,这里使用的是mysql_client
mysql_client | Dart package (pub.dev)
根据官方页面介绍,这个插件的功能有
- 创建链接池
- 创建单链接
- CRUD操作(插入、删除、查询、修改)
我们首先编写一个最最简单的Flutter界面,包含两个按钮:尝试链接、插入数据import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('MySQL Insert Example'), ), body: Center( child: FutureBuilder<void>( future: _insertData(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { if (snapshot.hasError) { return Text('Error: ${snapshot.error}'); } else { return Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ ElevatedButton( onPressed: (), child: Text('Connect to MySQL'), ), SizedBox(height: 20), ElevatedButton( onPressed: (), child: Text('Insert Data'), ), ], ); } } else { return CircularProgressIndicator(); } }, ), ), ), ); } }
显而易见,后续的SQL操作需要编写独立的函数放在类里,并在ElevatedButton
中的onPressed()
里使用,这样点击按钮后执行我们编写的MySQL操作函数
安装包
flutter pub add mysql_client
引用包
import 'package:mysql_client/mysql_client.dart';
这里给出链接的函数
Future<void> _insertData() async { //async是异步操作
try {
print("Connecting to mysql server...");
// create connection
final conn = await MySQLConnection.createConnection( //链接MySQL服务器
host: "127.0.0.1", //这里链接云端服务器直接改IP就够了
port: 3306,
userName: "root",
password: "",
databaseName: "test1", // optional
);
await conn.connect();
// insert some rows
var res = await conn.execute(
"INSERT INTO tabletest1 (name, email, age) VALUES (:name, :email, :age )",
{ //上面这句其实就是MySQL命令行操作语句
"name": "aaaaa", //这一部分根据表的格式和自己想插入的数据写
"email": "aaaaa.com",
"age": 20,
},
);
print(res.affectedRows);
// close all connections 操作结束后要关闭链接
await conn.close();
} catch (e) {
print('Error: $e');
}
}
4. 完整程序
// main.dart
import 'package:flutter/material.dart';
import 'package:mysql_client/mysql_client.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('MySQL Insert Example'),
),
body: Center(
child: FutureBuilder<void>(
future: _insertData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () => _showSnackbar(context, 'Connected'),
child: Text('Connect to MySQL'),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () => _showSnackbar(context, 'Inserted Data'),
child: Text('Insert Data'),
),
],
);
}
} else {
return CircularProgressIndicator();
}
},
),
),
),
);
}
Future<void> _insertData() async {
try {
print("Connecting to mysql server...");
// create connection
final conn = await MySQLConnection.createConnection(
host: "127.0.0.1",
port: 3306,
userName: "root",
password: "",
databaseName: "test1", // optional
);
await conn.connect();
// insert some rows
var res = await conn.execute(
"INSERT INTO tabletest1 (name, email, age) VALUES (:name, :email, :age )",
{
"name": "aaaaa",
"email": "aaaaa.com",
"age": 20,
},
);
print(res.affectedRows);
// close all connections
await conn.close();
} catch (e) {
print('Error: $e');
}
}
void _showSnackbar(BuildContext context, String message) { //APP底部的提示信息
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(message)),
);
}
}