Flutter如何在SharedPreferences存储字符串列表并在Widget中展示
解决方案
第一步:添加依赖
在项目的pubspec.yaml文件中添加shared_preferences依赖:
dependencies: flutter: sdk: flutter shared_preferences: ^2.2.2 # 可替换为官方当前最新版本
添加完成后执行flutter pub get安装依赖。
第二步:修改原有代码实现存储+展示逻辑
我们需要将原有的Result组件改为StatefulWidget,实现进入页面时自动存储当前记录、读取历史记录、渲染历史列表的逻辑,完整修改后代码如下:
import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'home.dart'; class Result extends StatefulWidget { final String selectedLevel; final String timeTakenInmin; const Result({Key? key, required this.selectedLevel,required this.timeTakenInmin}) : super(key: key); @override State<Result> createState() => _ResultState(); } class _ResultState extends State<Result> { List<Map<String, String>> historyList = []; @override void initState() { super.initState(); _saveAndLoadHistory(); } // 存储当前记录+加载历史记录的方法 _saveAndLoadHistory() async { final prefs = await SharedPreferences.getInstance(); // 1. 先读取已有的历史记录 List<String>? oldHistory = prefs.getStringList('game_history'); oldHistory ??= []; // 2. 把当前记录拼接成字符串加入列表,格式为 等级|耗时 String currentRecord = "${widget.selectedLevel}|${widget.timeTakenInmin}"; oldHistory.add(currentRecord); // 3. 存回SharedPreferences await prefs.setStringList('game_history', oldHistory); // 4. 把字符串列表转成可渲染的Map列表 List<Map<String, String>> tempList = []; for (String record in oldHistory) { List<String> parts = record.split('|'); if(parts.length == 2) { tempList.add({ "level": parts[0], "time": parts[1] }); } } setState(() { historyList = tempList.reversed.toList(); // 倒序展示,最新的记录在最上面 }); } @override Widget build(BuildContext context) { var size = MediaQuery.of(context).size; return WillPopScope( onWillPop: () =>Future.value(false), child: Scaffold( body: Center( child: Column( children: [ Expanded(flex:2,child: LayoutBuilder( builder: (context,constraints) => Container( color: const Color(0xFF317C84), child: Center( child: const Text('Your Result',style: TextStyle( color: Colors.black54,fontWeight: FontWeight.bold,fontSize: 30 ),), ), ), )), Expanded(flex:1,child: LayoutBuilder( builder: (context,constraints) => Container( decoration: BoxDecoration( image: DecorationImage( image: AssetImage("assets/reporticon.png",),scale: 4, ) ), ), )), Expanded(flex:1,child: LayoutBuilder( builder: (context,constraints) => Container(height: size.height*.3, child: Column( children: [ DataTable( columns: const [ DataColumn(label: Text('Level Selected')), DataColumn(label: Text('Time Taken')), ], rows: [ DataRow(cells: [ DataCell(Text(widget.selectedLevel)), DataCell(Text(widget.timeTakenInmin)), ]) ], ), ])), )), // 新增历史记录展示区域,对应你需要放置历史记录的位置 Expanded(flex:2, child: LayoutBuilder( builder: (context, constraints) { if(historyList.isEmpty) { return const Center(child: Text("暂无历史记录"),); } return SingleChildScrollView( child: Column( children: [ const Padding( padding: EdgeInsets.symmetric(vertical: 8.0), child: Text("历史记录", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),), ), DataTable( columns: const [ DataColumn(label: Text('历史等级')), DataColumn(label: Text('历史耗时')), ], rows: historyList.map((record) { return DataRow(cells: [ DataCell(Text(record['level']!)), DataCell(Text(record['time']!)), ]); }).toList(), ) ], ), ); }, )), Expanded(flex:1,child: LayoutBuilder( builder: (context,constraints) => Center( child: ElevatedButton(style: ButtonStyle(backgroundColor: MaterialStateProperty.all(const Color(0xFF317C84))), onPressed: (){ Navigator.push( context, MaterialPageRoute( builder: (context) { return const Home(); }, ), ); }, child: const Text("Exit"), ), ), )), ], ) ), ), ); } }
功能说明
- 每次进入Result页面时,会自动把当前的对局记录存储到SharedPreferences中
- 历史记录默认倒序展示,最新的记录排在最前面
- 历史记录区域做了滚动处理,记录数量较多时也不会出现布局溢出
- 首次使用无历史记录时会展示占位提示
内容的提问来源于stack exchange,提问作者Sonu Sharma
相关产品推荐
相关产品推荐

