The following is my JSON file which include the data:
[
{
"city": "City1",
"attractions": [
"attraction1",
"attraction2"
],
},
{
"city": "city2",
"attractions": [
"attraction1",
"attraction2",
],
},
]
My implementation code is a listview builder that gets data from the JSON file. the code also have an option option to save cities as favorite that can be shown in another page as a list of saved favorites:
class Index extends StatefulWidget {
@override
_IndexState createState() => _IndexState();
}
List data;
List<Cities> citylist = List();
List<Cities> citysavedlist = List();
int index;
class _IndexState extends State<Index> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: listView(),
);
}
Future<String> fetchData() async {
String data =
await DefaultAssetBundle.of(context).loadString("assets/data.json");
final jsonResult = json.decode(data);
this.setState(() {
jsonResult
.forEach((element) => citylist.add(new Cities.fromJson(element)));
});
return "Success!";
}
@override
void initState() {
super.initState();
fetchData();
}
listView() {
return ListView.builder(
itemCount: citylist == null ? 0 : citylist.length,
itemBuilder: (context, index) {
return Column(
children: <Widget>[_buildRow(index, citylist)],
);
},
);
}
Widget _buildRow(index, citylist) {
final bool alreadySaved = citysavedlist.contains(citylist[index]);
return Padding(
padding: const EdgeInsets.only(top: 5.0, left: 5.0, right: 5.0),
child: Card(
child: ListTile(
title:
Text(citylist[index].title, style: TextStyle(fontSize: 22.0)),
trailing: IconButton(
icon: Icon(
alreadySaved ? Icons.star : Icons.star_border,
color: alreadySaved ? Colors.blue : Colors.blue,
),
onPressed: () {
setState(() {
if (alreadySaved) {
citysavedlist.remove(citylist[index]);
} else {
citysavedlist.add(citylist[index]);
}
});
},
), //subtitle: Text(subtitle),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Detail(citylist[index])));
}),
),
);
}
void _pushSaved() {
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (BuildContext context) {
final Iterable<ListTile> tiles = citysavedlist.map(
(Cities pair) {
return ListTile(
title: Text(
pair.city,
),
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => Detail(pair)));
});
},
);
final List<Widget> divided = ListTile.divideTiles(
context: context,
tiles: tiles,
).toList();
return Scaffold(
appBar: AppBar(
title: const Text('Saved Suggestions'),
),
body: ListView(children: divided),
);
},
),
);
}
}
This is model class :
List<Cities> citiesFromJson(String str) =>
List<Cities>.from(json.decode(str).map((x) => Cities.fromJson(x)));
String citiesToJson(List<Cities> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Cities {
Cities({
this.city,
this.attractions,
});
String city;
List<String> attractions;
factory Cities.fromJson(Map<String, dynamic> json) => Cities(
city: json["city"],
attractions: List<String>.from(json["attractions"].map((x) => x)),
);
Map<String, dynamic> toJson() => {
"city": city,
"attractions": List<dynamic>.from(attractions.map((x) => x)),
};
}
Now I am facing an issue which is the saved favorite cities is not stored, so when the app is closed and reopened again, the favorite list will disappear as it is not stored.
I know that there is a plugin called Shared preferences that will do this functionality of storing saved data, but I am not able to integrate this plugin into my code. Can someone help to do that.
First what you have to do is get the package in the pubspec then
import 'package:shared_preferences/shared_preferences.dart';
SharedPreferences prefs = await SharedPreferences.getInstance();
Now to save the json data you have to do is
prefs.setString('mydata', json.encode(yourjsondata));
to retrieve this data you must use the exact name you assigned , in my case 'mydata'
json.decode(preferences.getString('mydata'))
Remember If you want to save so many data items sqflite or hive is recommended or If you still want to use shared_preferences you might save a counter as
To save
var counter = (prefs.getInt('Counter')??0)+1;
prefs.setString('Counter:$counter', json.encode(yourdata));
To get back in the order
var listCount = preferences.getInt('Counter');
loop through using listCount and then use
json.decode(preferences.getString('Counter:$variable'))