Flutter_学习记录_本地存储数据
- 创业
- 2025-09-20 08:51:01

背景
项目中经常会有本地存储数据的需求,例如,本地存储搜索页面“搜索数据”, 如下图:
思路 进入页面时,加载本地数据点击搜索时,将搜索数据存储到本地:先读取本地数据,如果有数据,就追加数据,并保存;如果本地没数据,就直接保存。点击“清空所有历史记录”时,删除本地的搜索记录的数据长按某一条数据时,展示“确认删除”弹框,删除某条数据。 代码实现用三方库shared_preferences来实现,在项目中引入shared_preferences库:
创建一个StorageService类,来封装对应的方法,代码如下:
import 'dart:convert'; import 'package:shared_preferences/shared_preferences.dart'; class StorageService { static final _searchKey = "SearchHistory"; // 获取搜索的历史记录 static Future<List<String>> getSearchHistoryString() async { final shareInstance = await SharedPreferences.getInstance(); try { final historyString = shareInstance.getString(_searchKey); print("搜索历史记录 = $historyString"); if (historyString != null) { List historyList = json.decode(historyString); return historyList.map((value){ return "$value"; }).toList(); } else { print("搜索历史记录 没有数据"); return []; } } catch (e) { print("搜索历史记录 没有数据"); return []; } } /* 存储搜索历史记录 如果有数据,就追加数据,然后存储; 如果没有数据,就新建List,添加数据,然后存储; */ static Future<void> setSearchHistoryString(String keyword) async { final shareInstance = await SharedPreferences.getInstance(); try { final historyString = shareInstance.getString(_searchKey); if (historyString != null) { List historyList = json.decode(historyString); historyList.add(keyword); final dataString = json.encode(historyList); print("历史记录 = $dataString"); shareInstance.setString(_searchKey, dataString); } else { List historyList = [keyword]; final dataString = json.encode(historyList); print("历史记录 = $dataString"); shareInstance.setString(_searchKey, dataString); } } catch (e) { List historyList = [keyword]; final dataString = json.encode(historyList); print("历史记录 = $dataString"); shareInstance.setString(_searchKey, dataString); } } // 删除某条历史记录 static Future<List<String>> removeSearchKeyword(String keyword) async { final shareInstance = await SharedPreferences.getInstance(); try { final historyString = shareInstance.getString(_searchKey); if (historyString != null) { List historyList = json.decode(historyString); List<String> historyStringList = historyList.map((value){ return "$value"; }).toList(); historyStringList.remove(keyword); final dataString = json.encode(historyStringList); print("历史记录 = $dataString"); shareInstance.setString(_searchKey, dataString); return historyStringList; } else { return []; } } catch (e) { return []; } } // 清空搜索历史记录 static Future<void> clearSearchHistory() async { final shareInstance = await SharedPreferences.getInstance(); try { shareInstance.remove(_searchKey); } catch (e) { print(e); } } } 创建删除的提示框: import 'dart:ffi'; import 'package:flutter/material.dart'; class ShowAlertWidget { /// 显示一个带有标题和内容的对话框 /// /// 参数: /// - `context`: 当前上下文 /// - `title`: 对话框标题 /// - `content`: 对话框内容 /// /// 返回值: /// - 0: 用户点击了 "取消" /// - 1: 用户点击了 "确定" static Future<int> showAlert(BuildContext context, String title, String content) async { final value = await showDialog<int>( context: context, builder: (BuildContext context) { return AlertDialog( title: Text(title), content: Text(content), actions: [ TextButton( onPressed: () { Navigator.pop(context, 0); // 返回值为 0,表示取消 }, child: Text("取消"), ), TextButton( onPressed: () { Navigator.pop(context, 1); // 返回值为 1,表示确定 }, child: Text("确定"), ), ], ); }, ) ?? 0; // 如果用户直接关闭对话框,则默认返回 0(取消) print("value = $value"); return value; } } 使用的地方://
[ 进入页面的时候,加载数据] @override void initState() { super.initState(); // 进入页面的时候,加载数据 StorageService.getSearchHistoryString().then((list){ setState(() { _historySearchData = list; }); }); } 点击搜索时,将搜索数据存储到本地 onTap: (){ if (_searchTextValue.isEmpty) { return; } // 存储数据 StorageService.setSearchHistoryString(_searchTextValue); // 进入商品分类后,点击返回,可以跳过搜索页,直接返回到根视图 Navigator.pushReplacementNamed(context, "/productList", arguments: { "keyword": _searchTextValue }); } 点击“清空所有历史记录”时,删除本地的搜索记录的数据 onTap: (){ StorageService.clearSearchHistory(); setState(() { _historySearchData = []; }); } 长按某一条数据时,展示“确认删除”弹框,删除某条数据 onLongPress: (){ ShowAlertWidget.showAlert(context, "删除提醒", "确认要删除这条数据吗").then((value) { if (value == 1) { StorageService.removeSearchKeyword(keyword).then((list){ setState(() { _historySearchData = list; }); }); } }); } 完整代码案例 import 'package:fangjd/CommonWidget/ShowAlertWidget.dart'; import 'package:fangjd/Services/ScreenAdapter.dart'; import 'package:fangjd/Services/StorageService.dart'; import 'package:flutter/material.dart'; class SearchPage extends StatefulWidget { const SearchPage({super.key}); @override State<SearchPage> createState() => _SearchPageState(); } class _SearchPageState extends State<SearchPage> { final List<String> _hotSearchData = ["超级秒杀", "办公电脑", "儿童汽车", "唇彩唇蜜", "哪吒2"]; List<String> _historySearchData = ["贝亲奶瓶", "纸尿裤", "婴儿衣架", "包被"]; String _searchTextValue = ""; // 设置搜索条 Widget _searchInputWidget() { return Container( padding: EdgeInsets.only(left: Screenadapter.width(20)), height: Screenadapter.height(80), decoration: BoxDecoration( color: Color.fromRGBO(233, 233, 233, 0.9), borderRadius: BorderRadius.circular(Screenadapter.height(40)), ), child: TextField( autofocus: false, decoration: InputDecoration( // 设置内容的间距 contentPadding: EdgeInsets.all(10), // 设置图标 prefixIcon: Icon(Icons.search, size: 18, color: Colors.black45), // 设置前置图标的约束 prefixIconConstraints: BoxConstraints( //添加内部图标之后,图标和文字会有间距,实现这个方法,不用写任何参数即可解决 minWidth: 30.0 ), // 设置提示文字 hintText: "请输入你想搜索的商品", // 设置提示文字的样式 hintStyle: TextStyle(fontSize: 16, color: Colors.black45), // 去掉输入框底部的线 border: OutlineInputBorder( borderSide: BorderSide.none, ), ), onChanged: (value) { _searchTextValue = value; }, ), ); } // 设置搜索的按钮 Widget _searchItemWiget() { return InkWell( onTap: (){ if (_searchTextValue.isEmpty) { return; } // 存储数据 StorageService.setSearchHistoryString(_searchTextValue); // 进入商品分类后,点击返回,可以跳过搜索页,直接返回到根视图 Navigator.pushReplacementNamed(context, "/productList", arguments: { "keyword": _searchTextValue }); }, child: Container( padding: EdgeInsets.only(right: Screenadapter.width(30)), height: Screenadapter.height(80), width: Screenadapter.width(100), child: Center( child: Text("搜索", style: TextStyle(fontSize: 18)), ), ), ); } // 热搜的视图 Widget _hotSearchWidget() { return SizedBox( height: Screenadapter.height(180), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ SizedBox(width: 10), Text("热搜", style: TextStyle(fontSize: 18, fontWeight: FontWeight.w800)) ], ), SizedBox(height: 10), SingleChildScrollView( padding: EdgeInsets.only(left: 10), scrollDirection: Axis.horizontal, child: Row( children: _hotSearchData.map((value){ return InkWell( onTap: (){ // 进入商品分类后,点击返回,可以跳过搜索页,直接返回到根视图 Navigator.pushReplacementNamed(context, "/productList", arguments: { "keyword": value }); }, child: Container( height: 30, padding: EdgeInsets.only(left: 10, right: 10), margin: EdgeInsets.only(right: 10), color: Colors.grey[200], child: Center(child: Text(value)), ), ); }).toList(), ), ), SizedBox(height: 10), Container( height: 15, color: Colors.grey[200], ) ], ), ); } // 历史搜索 Widget _historSearchTitleWidget() { return SizedBox( height: 50, child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ Expanded( child: Container( padding: EdgeInsets.only(top: 14, bottom: 14, left: 10), child: Text("历史搜索", style: TextStyle(fontSize: 18, fontWeight: FontWeight.w800), textAlign: TextAlign.start), )), Divider(height: 1, color: Colors.grey[200]) ], ), ); } // 搜索页面的内容视图 Widget _searchHotAndHistroyWidget() { return ListView.builder( itemBuilder: (context, index){ if (index == 0) { return _hotSearchWidget(); } if (index == 1) { return _historSearchTitleWidget(); } final keyword = _historySearchData[index -2]; return Container( padding: EdgeInsets.only(left: 10, right: 10), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ InkWell( onTap: (){ // 进入商品分类后,点击返回,可以跳过搜索页,直接返回到根视图 Navigator.pushReplacementNamed(context, "/productList", arguments: { "keyword": keyword }); }, onLongPress: (){ ShowAlertWidget.showAlert(context, "删除提醒", "确认要删除这条数据吗").then((value) { if (value == 1) { StorageService.removeSearchKeyword(keyword).then((list){ setState(() { _historySearchData = list; }); }); } }); }, child: Container( width: double.infinity, padding: EdgeInsets.only(top: 14, bottom: 14), child: Text(keyword, style: TextStyle(fontSize: 16), textAlign: TextAlign.start), ), ), Divider(height: 1, color: Colors.grey[200]) ], ), ); }, itemCount: _historySearchData.isNotEmpty ? _historySearchData.length + 2 : 1, ); } // 删除的按钮 Widget _deleteHistoryWiget() { return Container( margin: EdgeInsets.only(left: Screenadapter.width(60), right: Screenadapter.width(60)), height: Screenadapter.height(100), decoration: BoxDecoration( border: Border.all( width: 1, color: Colors.black45 ), borderRadius: BorderRadius.circular(5) ), child: InkWell( onTap: (){ StorageService.clearSearchHistory(); setState(() { _historySearchData = []; }); }, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.delete), Text("清空所有历史记录") ], ), ), ); } @override void initState() { super.initState(); StorageService.getSearchHistoryString().then((list){ setState(() { _historySearchData = list; }); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: _searchInputWidget(), actions: [ _searchItemWiget() ], ), body: Container( padding: EdgeInsets.only(bottom: 30), child: Column( children: [ Expanded(child: _searchHotAndHistroyWidget()), _deleteHistoryWiget() ], ), ), ); } }Flutter_学习记录_本地存储数据由讯客互联创业栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Flutter_学习记录_本地存储数据”