如何将服务器加载数据持久化到本地SQLite,避免App关闭后丢失
解决SQLite数据库服务器数据重启丢失问题
核心问题分析
你的数据库初始化函数每次启动App都会把assets里的初始数据库覆盖到本地文档目录,这就导致你之前从服务器加载并保存的数据,在App重启后被初始数据完全覆盖,自然看不到了。
第一步:修复数据库初始化逻辑
修改initDb函数,先判断本地数据库文件是否存在,只有不存在的时候才从assets复制,存在则直接打开:
Future<Database> initDb() async { if (kIsWeb) { // 这里补充Web端的数据库初始化逻辑,比如使用sqflite_web等适配库 return Future.error("Web端暂未实现"); } else { Directory documentDirectory = await getApplicationDocumentsDirectory(); String path = join(documentDirectory.path, "data_4us.db"); final File dbFile = File(path); // 检查本地数据库是否存在,不存在才从assets复制初始数据 if (!await dbFile.exists()) { ByteData data = await rootBundle.load(join('data', '4us.db')); List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); await dbFile.writeAsBytes(bytes); } // 直接打开本地已有的数据库(包含之前保存的服务器数据) var ourDb = await openDatabase(path); return ourDb; } }
第二步:实现服务器数据的本地存储
当你从服务器获取到数据后,需要编写对应的插入/更新SQL逻辑,把数据写入本地数据库。以下是示例(假设你有一个user表):
1. 编写数据插入/更新方法
Future<void> saveServerData(List<Map<String, dynamic>> serverData) async { final db = await initDb(); // 开启事务,批量操作更高效且保证数据一致性 await db.transaction((txn) async { for (var item in serverData) { // 使用replace策略:如果主键重复则更新,否则插入 await txn.insert( 'user', item, conflictAlgorithm: ConflictAlgorithm.replace, ); } }); }
2. 在获取服务器数据后调用存储方法
// 从服务器拉取并保存数据的示例函数 Future<void> fetchAndSaveServerData() async { // 1. 请求服务器接口获取数据 final response = await http.get(Uri.parse("你的服务器数据接口地址")); if (response.statusCode == 200) { List<dynamic> rawData = jsonDecode(response.body); List<Map<String, dynamic>> serverData = List.from(rawData); // 2. 将服务器数据写入本地数据库 await saveServerData(serverData); } }
第三步:验证数据留存
修改后,第一次启动App会复制assets的初始数据库;后续启动直接打开本地已有的数据库。调用fetchAndSaveServerData后,服务器数据会被持久化到本地,即使关闭App再重启,查询数据库就能看到这些留存的数据了。
内容的提问来源于stack exchange,提问作者Namarig Wahbi
相关产品推荐
相关产品推荐

