《Flutter 从0到1构建大前端应用》读后感—第8章【持久化】

本文深入探讨了Flutter中三种本地存储方式:shared_preferences、SQLite数据库和文件存储的使用方法及示例,为开发者提供了全面的存储解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Flutter 《从0到1构建大前端应用》-所有知识点架构

一丶 shared_preferences 本地存储

导入第三方依赖: shared_preferences: ^0.5.1+1

1.shared_preferences 的常用操作

  SharedPreferences prefs = await SharedPreferences.getInstance();
  prefs.setString(key,value);

  SharedPreferences prefs = await SharedPreferences.getInstance();
  prefs.remove(key);

  SharedPreferences prefs = await SharedPreferences.getInstance();
  prefs.getString(key);

2.shared_preferences 举例

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class SharedPreferencesPage extends StatefulWidget {
  SharedPreferencesPage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _SharedPreferencesPageState createState() => _SharedPreferencesPageState();
}

class _SharedPreferencesPageState extends State<SharedPreferencesPage> {

  int _count = 0;     //数值

  @override
  void initState() {      //初始化生命周期方法
    super.initState();
    _getCounter();
  }

  void _incrementCounter() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();    //实例化 SharedPreferences对象
    int counter = (prefs.getInt("counter") ?? 0) + 1;   //取出值+1
    setState(() {   //更新页面
      _count = counter;
    });
    await prefs.setInt('counter', counter);   //保存值
  }

  _getCounter() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    setState(() {
      _count = prefs.get('counter') ?? 0;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              '点击数:' + _count.toString(),
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,     //点击悬浮按钮时
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

二丶 SQLite数据库

1.sqllite 依赖库简介
第三方库: sqflite: ^1.1.3

获取和删 database

在这里插入代码片

2.封装 SQL Helpers

db_helpers.dart

import 'dart:io';

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

final String tableUser = 'user';    //表名
final String columnId = '_id';      //id
final String columnName = 'name';   //用户名

class User {
  int id;         //id
  String name;    //用户名

  Map<String, dynamic> toMap() {
    var map = <String, dynamic>{    //创建map数据,并赋值给用户名
      columnName: name,
    };
    if (id != null) {
      map[columnId] = id; //赋值给id
    }
    return map;
  }

  User();

  //从Map数据中取出对应值并赋值给实体bean的成员变量
  User.fromMap(Map<String, dynamic> map) {
    id = map[columnId];
    name = map[columnName];
  }
}

class DBProvider {
  DBProvider._();

  static final DBProvider db = DBProvider._();    //数据库提供者

  Database _database;     //数据库

  Future<Database> get database async {
    if (_database != null) return _database;
    _database = await initDB();     //如果数据库不存在,则在建立table的同时创建数据库,若表存在数据库不可能不存在
    return _database;   //返回数据库
  }

  initDB() async {
    //目录对象 = 获取应用文件目录
    Directory documentsDirectory = await getApplicationDocumentsDirectory();
    //路径 = 加入(目录对象路径,表名)
    String path = join(documentsDirectory.path, "UserDB.db");
    //打开数据库(路径,版本,数据库)
    return await openDatabase(path, version: 1, onOpen: (db) {},
        onCreate: (Database db, int version) async {
      //创建表
      await db.execute('''                                        
            create table $tableUser ( 
              $columnId integer primary key autoincrement, 
              $columnName text not null)
            ''');
    });
  }

  //插入数据
  Future<User> insert(User user) async {
    final db = await database;    //获取数据库对象
    //返回数据库存入的id = 插入(表名,Map类型(用来传入需要添加的字段名和对应的取值))
    user.id = await db.insert(tableUser, user.toMap());
    return user;    //返回bean对象
  }

  //获取单个数据
  Future<User> getUser(int id) async {
    final db = await database;    //获取数据库对象
    //查询
    List<Map> maps = await db.query(tableUser,    //表名
        columns: [columnId, columnName],        //查询字段
        where: '$columnId = ?',                 //条件
        whereArgs: [id]);                       //where 子句的占位符参数值
    if (maps.length > 0) {    //若有数据
      return User.fromMap(maps.first);    //从Map数据中取出对应值
    }
    return null;
  }

  //获取全部数据
  Future<List<User>> getAllUser() async {
    final db = await database;        //获取数据库对象
    var res = await db.query("User");   //表名
    List<User> list =
        res.isNotEmpty ? res.map((c) => User.fromMap(c)).toList() : []; //isNotEmpty 不为空
    return list;
  }

  //删除数据
  Future<int> delete(int id) async {
    final db = await database;     //获取数据库对象
    return await db.delete(tableUser, where: '$columnId = ?', whereArgs: [id]);
  }

  //更新数据
  Future<int> update(User user) async {
    final db = await database;      //获取数据库对象
    return await db.update(tableUser, user.toMap(),     //表名,Map<修改字段,对应值>
        where: '$columnId = ?', whereArgs: [user.id]);  //id = 占位符,where字句占位符所对应的值
  }

  //删除所有数据(删除表)
  removeAll() async {
    final db = await database;     //获取数据库对象
    db.delete(tableUser);     //删除表
  }

  //关闭资源
  Future close() async {
    final db = await database;  //获取数据库对象
    db.close(); //关闭
  }
}

3.sqllite 实现员工打卡实例

数据库封装类在上面:db_helpers.dart

CheckInPage.dart

import 'package:flutter/material.dart';
import 'package:flutter_store/check_in_result.dart';
import 'package:flutter_store/db_helpers.dart';
import 'package:shared_preferences/shared_preferences.dart';

class CheckInPage extends StatefulWidget {
  CheckInPage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _CheckInPageState createState() => _CheckInPageState();
}

class _CheckInPageState extends State<CheckInPage> {
  final TextEditingController textTitleEditingController =    //文本编辑器对象
      new TextEditingController();

  _save() {
    User user = User();   //实例化实体bean
    user.name = textTitleEditingController.text;  //bean.用户名=得到文本编辑器的内容
    DBProvider.db.insert(user);   //插入数据
    Navigator.of(context).push(         //跳转到 CheckInResult 页面
      new MaterialPageRoute(
        builder: (context) {
          return new CheckInResult();
        },
      ),
    );
  }

  _removeData() {     //清除所有数据
    DBProvider.db.removeAll();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
          child: Column(
        children: <Widget>[
          TextField(      //文本域
            controller: textTitleEditingController,   //控制者
            autofocus: true,    //自动对焦
            decoration: new InputDecoration(    //装饰:输入装饰
              hintText: '请输入用户名',
            ),
          ),
          RaisedButton(
            child: Text('保存'),
            onPressed: _save,     //保存数据
          ),
          RaisedButton(
            child: Text('清除数据'),
            onPressed: _removeData,
          )
        ],
      )),
    );
  }
}

CheckInResult.dart

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_store/db_helpers.dart';

class CheckInResult extends StatelessWidget {
  CheckInResult({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("已打卡人员")),
      body: FutureBuilder<List<User>>(    //未来建造者(List集合(bean对象))
        future: DBProvider.db.getAllUser(), //未来:得到所有数据(future类型)
        //上下文对象,异步数据      这个数据一定是先拿到了全部数据,才会执行下面的方法
        builder: (BuildContext context, AsyncSnapshot<List<User>> snapshot) {
          if (snapshot.hasData) {       //若数据库中有数据
            return ListView.builder(
              itemCount: snapshot.data.length,  //数据长度
              //每一个item:(上下文对象,  下标)
              itemBuilder: (BuildContext context, int index) {
                User item = snapshot.data[index];   //取出每一个bean对象
                return ListTile(
                  title: Text(item.name), //用户名
                );
              },
            );
          } else {
            return Center(child: CircularProgressIndicator());    //若没数据:显示圆形进度指示器
          }
        },
      ),
    );
  }
}

三丶 文件形式存储

1.path_provider简介

第三方库: path_provider: ^0.5.0+1

【1】获取临时目录

	Directory tempDir = await getTemporaryDirect();
	String tempPath = tempDir.path;

【2】获取应用文档目录

	Directory appDocDir = await getApplicationDocumentsDirectory();
	String appDocPath = appDocDir.path;

【3】获取外部存储目录

	Directory externalDir = await getExternalStorageDirectory();
	String externalPath = externalDir.path;

注意:iOS 平台上没有外部存储目录的概念,这一点在实际开发中需要注意并区分

2.一个简单的日记本示例

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';

class FileProviderPage extends StatefulWidget {
  final InfoStorage storage;      //信息存储
  final String title;             //标题

  FileProviderPage({Key key, this.title, this.storage}) : super(key: key);

  @override
  _FileProviderPageState createState() => _FileProviderPageState();
}

class _FileProviderPageState extends State<FileProviderPage> {
  final TextEditingController textTitleEditingController =    //文本编辑器对象
      new TextEditingController();
  String _info;

  @override
  void initState() {    //初始化生命周期函数
    super.initState();
    widget.storage.readInfo().then((String info) {  //获取指定文件数据
      setState(() {     //更新页面
        _info = info;
      });
    });
  }

  //保存
  Future<File> _saveInfo() async {
    setState(() {   //先更新页面
      _info = textTitleEditingController.text;
    });

    return widget.storage.writeInfo(_info);   //将新数据写入文件中
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('一个简单的日记本')),
      body: Column(
        children: <Widget>[
          TextField(
            controller: textTitleEditingController, //控制者
            autofocus: true,    //自动对焦
            decoration: new InputDecoration(    //装饰:输入装饰
              hintText: _info,
            ),
          ),
          RaisedButton(
            child: Text('保存'),
            onPressed: _saveInfo,
          ),
          Text(_info ?? ""),
        ],
      ),
    );
  }
}

class InfoStorage {
  Future<String> get _localPath async {
    final directory = await getApplicationDocumentsDirectory(); // 目录对象 = 得到应用文件目录
    return directory.path;    //目录路径
  }

  //得到本地存储文件
  Future<File> get _localFile async {
    final path = await _localPath;    //得到本地存储路径
    return File('$path/info.txt');  //打开文件(目录路径/文件名)
  }

  Future<String> readInfo() async {
    try {
      final file = await _localFile;    //得到本地存储对象
      String info = await file.readAsString();  //读取文件数据,返回值是字符串
      print(info);    //控制台打印
      return info;    //返回读取文件的字符串结果
    } catch (e) {
      return "error"; //如果有异常,则返回error
    }
  }

  Future<File> writeInfo(String info) async {
    final file = await _localFile;  //得到本地存储对象
    return file.writeAsString(info);  //写入数据
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王睿丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值