当前位置:   article > 正文

Flutter 本地数据存储(文件、SharedPreferences 、数据库 sqlite)使用示例_flutter sharedprefresh和sqlite哪个快

flutter sharedprefresh和sqlite哪个快

Flutter 提供了三种数据持久化方法,即文件、SharedPreferences 与数据库

文件

Flutter 提供了两种文件存储的目录,即临时(Temporary)目录与文档(Documents)目录:

  • 临时目录是操作系统可以随时清除的目录,通常被用来存放一些不重要的临时缓存数据。这个目录在 iOS 上对应着 NSTemporaryDirectory 返回的值(网上搜集的信息,对 iOS 不熟悉故不确定对错),而在 Android上则对应着 getCacheDir 返回的值。

  • 文档目录则是只有在删除应用程序时才会被清除的目录,通常被用来存放应用产生的重要数据文件。在 iOS上,这个目录对应着 NSDocumentDirectory (网上搜集的信息,对iOS不熟悉故不确定对错),而在 Android上则对应着 AppData 目录。

如何在Flutter中获取上述两个目录地址呢?这里使用到的是 path_provider库

先在pubspec.yaml中添加依赖,然后点击AndroidStudio右上角的 packages get

dependencies:
  path_provider: ^1.6.5
  • 1
  • 2

接下来就可以获取到以上两个目录路径了:

// 获取临时目录
Directory tempDir = await getTemporaryDirectory();
String tempPath = tempDir.path;

// 获取文档目录
Directory appDocDir = await getApplicationDocumentsDirectory();
String appDocPath = appDocDir.path;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

接下来我们通过示例来看一下效果。

示例

创建文件并写入数据,随后将数据读取出来。由于文件读写一般比较耗时且容易出错,为了保证程序的健壮性,需要异步Futures以及 try catch使用。

首先在文档目录创建文件:

Future<File> get _localFile async {
	// 存在文档目录
    final directory = await getApplicationDocumentsDirectory();
    final path = directory.path;
    // 使用绝对路径
    return File('$path/content.txt');
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

接着在文件中写入数据:

Future<File> writeContent(String content) async {
	// 获取到文件
    final file = await _localFile;
    // 执行写入
    return file.writeAsString(content);
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

最后将上一步写入的数据读取出来:

Future<String> readContent() async {
    try {
      // 获取到文件
      final file = await _localFile;
      // 执行读取
      String contents = await file.readAsString();
      return contents;
    } catch (e) {
      return "";
    }
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

效果图:
在这里插入图片描述

SharedPreferences

文件比较适合大量的、有序的数据持久化,如果我们只是需要缓存少量的键值对信息(比如记录用户是否阅读了公告,或是简单的计数),则可以使用 SharedPreferences。

接下来我们通过示例来看一下效果。

示例

在这里插入图片描述
首先引入库:shared_preferences

dependencies:
  shared_preferences: ^0.5.6+3

  • 1
  • 2
  • 3

然后往 SP 中写入数据:

// 获得实例
Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
// 写入数据
_prefs.then((sp) => {
  sp.setString('hello', '你好 SharedPreferences')
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

最后将之前写入的数据读取出来:

// 获得实例
Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
// 取出数据
_prefs.then((sp) {
 setState(() {
   mContent = sp.getString('hello');// 通过可 key 取出 value
 });
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

封装之后使用,源码地址:shared_preferences.dart

先看示例效果:

跳转网页那块有点慢,录制 gif 的时候直接跳过了,所以在详情页面会短暂显示空白

在这里插入图片描述
使用流程:

  1. 先获取到 SharedPrefernces 对象,
  2. 然后再点击搜索列表的 item 然后将数据存入到 SharedPrefernces中,
  3. 最后在历史面板展示 SharedPrefernces 中的数据。

具体使用可查看 Flutter-WanAndroid 项目

数据库 sqlite

SharedPrefernces 的使用固然方便,但这种方式只适用于持久化少量数据的场景,我们并不能用它来存储大量数据。原因是在 Android中使用 SharedPrefernces 存储的文件过大会导致读取速度变慢还可能出现内存抖动问题,iOS不熟悉这块也没法描述。为了解决以上问题,通常会选用 sqlite 数据库来本地化存储稍大量的数据。

示例

往数据库中添加三个学生的数据,然后读取出学生的姓名。

在这里插入图片描述
1. 首先引入库:sqflite

dependencies:
  ...
  sqflite: ^1.3.0
  • 1
  • 2
  • 3

2. 创建数据库,并调用初始化方法,我这里是在initState()调用:

join 方法可能会爆红,在顶部引入path库即可
import 'package:path/path.dart';

Future<void> initDataBase() async {
  dataBase = await openDatabase(
    join(await getDatabasesPath(), 'students_database.db'),
    onCreate: (db, version) => db.execute(
        "CREATE TABLE students(id TEXT PRIMARY KEY, name TEXT, score INTEGER)"),
    onUpgrade: (db, oldVersion, newVersion) {
      //dosth for migration
      print("old:$oldVersion,new:$newVersion");
    },
    version: 1,
  );
  print("database:$dataBase");
}

// 调用初始化
@override
void initState() {
  initDataBase();
  super.initState();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

3. 存入数据:

// 创建 Student 对象
class Student {
  String id;
  String name;
  int score;

  Student({
    this.id,
    this.name,
    this.score,
  });
  factory Student.fromJson(Map<String, dynamic> parsedJson) {
    return Student(
      id: parsedJson['id'],
      name: parsedJson['name'],
      score: parsedJson['score'],
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'name': name,
      'score': score,
    };
  }
}

// 插入数据库 中的 students 表
Future<void> insertStudent(Student std) async {
  await dataBase.insert(
    'students',
    std.toJson(),
    conflictAlgorithm: ConflictAlgorithm.replace,
  );
}

// 调用插入数据方法
insertData() async {
  var student1 = Student(id: '0', name: '张三', score: 90);
  var student2 = Student(id: '1', name: '李四', score: 80);
  var student3 = Student(id: '2', name: '王五', score: 85);

  // Insert a dog into the database.
  await insertStudent(student1);
  await insertStudent(student2);
  await insertStudent(student3);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

4. 取出数据:

// 查询 students 表的数据
Future<List<Student>> students() async {
  final List<Map<String, dynamic>> maps = await dataBase.query('students');
  return List.generate(maps.length, (i) => Student.fromJson(maps[i]));
}

// 转为 string 输出
getStudents() async {
    await students()
        .then((list) => list.forEach((s) => sb.writeln(s.toJson().toString())));
    setState(() {
      mContext = sb.toString();
    });
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

5. 关闭数据库:

@override
void dispose() {
  dataBase.close();
  super.dispose();
}
  • 1
  • 2
  • 3
  • 4
  • 5

以上就是数据库的基本使用,使用步骤略有繁琐,我们可以封装了之后再使用。
参考 flutter-go

封装之后使用,源码地址:

先看示例效果:

本地收藏数据库实现。跳转网页那块有点慢,录制 gif 的时候直接跳过了,所以在详情页面会短暂显示空白。

在这里插入图片描述

以下文件请在 Flutter-WanAndroid 项目中查找

使用流程:

  1. 初始化数据库对象,这里在main.dart文件中初始化。具体的初始化逻辑在utils/provider.dart文件中
 // 数据库初始化
  await provider.init(true);
  • 1
  • 2
  1. 然后我们将常见的数据操作(增删改查)放在utils/sql.dart文件中,便于操作数据库。
    在这里插入图片描述
  2. 接着就是具体的使用了。如收藏操作,在model/collect.dart文件中,先创建到 Collection 对象和在数据库中创建表格,并在里面实现model的数据库逻辑操作。
 // 例如:插入新收藏
  Future insert(Collection collection) {
    var result =
    sql.insert({'id': collection.id, 'title': collection.title, 'link':collection.link});
    return result;
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  1. 定义好逻辑操作之后,接着就是在合理的地方响应用户的输入了。这里是在详情页面用户点击收藏图标时调用model/collect.dart 中的 insert方法插入数据库。
 // 插入操作
_collectionControl
    .insert(Collection(
    id: widget.id.toString(),
    title: widget.title,
    link: widget.link))
    .then((result) {
  if (this.mounted) {
    setState(() {
      _hasCollected = true;
    });
    print("收藏成功");
    // 发送事件给 收藏页面,显示数据
    if (ApplicationEvent.event != null) {
      ApplicationEvent.event
          .fire(CollectionEvent(widget.title, _link, false));
    }
  }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  1. 最后在views/collection_page.dart页面展示收藏的数据。
  void _getList() {
    _collectionList.clear();
    _collectionControl.getAllCollection().then((resultList) {
      resultList.forEach((item) {
        _collectionList.add(item);
      });
      if (this.mounted) {
        setState(() {
          _collectionList = _collectionList;
        });
      }
    });
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

具体使用可查看 Flutter-WanAndroid 项目。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/308734
推荐阅读
相关标签
  

闽ICP备14008679号