网站运营推广选择乐云seo系统优化软件十大排名
背景
项目中经常会有本地存储数据的需求,例如,本地存储搜索页面“搜索数据”, 如下图:
思路
- 进入页面时,加载本地数据
- 点击搜索时,将搜索数据存储到本地:先读取本地数据,如果有数据,就追加数据,并保存;如果本地没数据,就直接保存。
- 点击“清空所有历史记录”时,删除本地的搜索记录的数据
- 长按某一条数据时,展示“确认删除”弹框,删除某条数据。
代码实现
-
用三方库
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;}
}
- 使用的地方:
//
- [ 进入页面的时候,加载数据]
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});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("清空所有历史记录")],),),);}void initState() {super.initState();StorageService.getSearchHistoryString().then((list){setState(() {_historySearchData = list;});});}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()],),),);}
}