How to save a list of objects locally in Flutter? - flutter

I have a page from which I need to save data locally as a list. To save, I use SharedPrefs, there, through the model, I save the data as a list. But I ran into a problem that I can not specify the format for receiving data List, tell me how can I save data as a list and receive data as a list?
class RecentlySearchedModel {
String name;
String address;
RecentlySearchedModel({
required this.name,
required this.address,
});
factory RecentlySearchedModel.fromJson(Map<String, dynamic> json) {
return RecentlySearchedModel(
name: json['name'] as String,
address: json['address'] as String,
);
}
Map<String, dynamic> toJson() {
return {
'name': name,
'address': address,
};
}
}
repository
#override
Future setResentlySearched({required List<RecentlySearchedModel> searchedList}) async {
final SharedPrefs prefs = SharedPrefs();
await prefs.setString(_name, jsonEncode( ))
}
#override
Future<List<RecentlySearchedModel>?> getResentlySearched() async {
final SharedPrefs prefs = SharedPrefs();
final data = await prefs.getString(_name);
if (data == null) return null;
return List<RecentlySearchedModel>.fromJson(
jsonDecode(data),
);
}

update your repository like this.
#override
Future setResentlySearched({required List<RecentlySearchedModel> searchedList}) async {
final SharedPrefs prefs = SharedPrefs();
await prefs.setString(_name, jsonEncode(searchedList.toJson());
}
#override
Future<List<RecentlySearchedModel>?> getResentlySearched() async {
final SharedPrefs prefs = SharedPrefs();
final data = await prefs.getString(_name);
if (data == null) return null;
Iterable l = json.decode(data);
List<RecentlySearchedModel> posts = List<RecentlySearchedModel>.from(l.map((model)=> RecentlySearchedModel.fromJson(model)));
return posts;
}

i havent try to complie, but its should be like this
Future setResentlySearched({required List<RecentlySearchedModel> searchedList}) async {
List<Map<String,dynamic>> listItem = searchedList.map((e)=> e.toJson()).toList();
String jsonString = jsonEncode(listItem);
final SharedPrefs prefs = SharedPrefs();
await prefs.setString(_name, jsonString)
}
and get it back
Future<List<RecentlySearchedModel>?> getResentlySearched() async {
final SharedPrefs prefs = SharedPrefs();
final data = await prefs.getString(_name);
if (data == null) return null;
return (jsonDecode(data) as List).map((e)=> RecentlySearchedModel.fromJson(e)).toList();
}

Related

How toGet data from api and save it into local database sqlite then show in listview (from local)

How to get data from api and save the data to locally database sqlite?
this is my code, but still got error in dio
can you guys help me
error dio
import 'package:bloggggg/employee_model.dart';
import 'package:bloggggg/db_provider.dart';
import 'package:flutter/cupertino.dart';
import 'package:http/http.dart' as http;
import 'package:dio/dio.dart';
class EmployeeApiProvider {
Future<List<Employee?>> getAllEmployees() async {
final url = "http://demo8161595.mockable.io/employee";
Response response = await Dio().get(url);
if(response.statusCode == 200){
return (response.data as List).map((employee) {
print('Inserting $employee');
DBProvider.db.createEmployee(Employee.fromJson(employee));
}).toList();
}else{
return response.data;
}
}
}
Save Api Data Function
save() async {
final dbHelper = DatabaseHelper.instance;
const url = "http://demo8161595.mockable.io/employee";
final result = await get(Uri.parse(url));
final response = jsonDecode(result.body);
Map<String, dynamic> row = DatabaseInsetItemModel(
name: response["name"] ?? "",
lName: response["lName"] ?? "",
mobile: response["mobile"] ?? "",
email: response["email"] ?? "",
cat: response["cat"] ?? "",
profile: response["profile"] ?? "")
.toJson();
print('insert stRT');
final id = await dbHelper.insertContact(row);
if (kDebugMode) {
print('inserted row id: $id');
}
}
DataBase Helper
class DatabaseHelper {
static final _databaseName = "MyDatabase.db";
static final _databaseVersion = 1;
static final table = 'category';
static final tableContact = 'contact';
static final columnId = '_id';
static final columnName = 'name';
static final columnLName = 'lname';
static final columnMobile = 'mobile';
static final columnEmail = 'email';
static final columnCategory = 'cat';
static final columnProfile = 'profile';
// make this a singleton class
DatabaseHelper._privateConstructor();
static final DatabaseHelper instance = DatabaseHelper._privateConstructor();
// only have a single app-wide reference to the database
static Database? _database;
Future<Database> get database async => _database ??= await _initDatabase();
Future<Database?> get database1 async {
if (_database == null) {
_database = await _initDatabase();
}
return _database;
}
// this opens the database (and creates it if it doesn't exist)
_initDatabase() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, _databaseName);
return await openDatabase(path,
version: _databaseVersion, onCreate: _onCreate);
}
// SQL code to create the database table
Future _onCreate(Database db, int version) async {
await db.execute('''
CREATE TABLE $table (
$columnId INTEGER PRIMARY KEY,
$columnName TEXT NOT NULL
)
''');
await db.execute('''
CREATE TABLE $tableContact (
$columnId INTEGER PRIMARY KEY,
$columnName TEXT NOT NULL,
$columnLName TEXT NOT NULL,
$columnMobile TEXT NOT NULL,
$columnEmail TEXT NOT NULL,
$columnCategory TEXT NOT NULL,
$columnProfile TEXT NOT NULL
)
''');
}
// Helper methods
// Inserts a row in the database where each key in the Map is a column name
// and the value is the column value. The return value is the id of the
// inserted row.
Future<int> insert(Map<String, dynamic> row) async {
Database? db = await instance.database;
return await db.insert(table, row);
}
Future<int> insertContact(Map<String, dynamic> row) async {
Database? db = await instance.database;
return await db.insert(tableContact, row);
}
// All of the rows are returned as a list of maps, where each map is
// a key-value list of columns.
Future<List<Map<String, dynamic>>> queryAllRows() async {
Database db = await instance.database;
return await db.query(table);
}
Future<List<Map<String, dynamic>>> queryAllRowsofContact() async {
Database db = await instance.database;
return await db.query(tableContact);
}
// All of the methods (insert, query, update, delete) can also be done using
// raw SQL commands. This method uses a raw query to give the row count.
Future<int> queryRowCount() async {
Database db = await instance.database;
return Sqflite.firstIntValue(
await db.rawQuery('SELECT COUNT(*) FROM $table')) ??
0;
}
// We are assuming here that the id column in the map is set. The other
// column values will be used to update the row.
Future<int> update(Map<String, dynamic> row) async {
Database db = await instance.database;
int id = row[columnId];
return await db.update(table, row, where: '$columnId = ?', whereArgs: [id]);
}
// Deletes the row specified by the id. The number of affected rows is
// returned. This should be 1 as long as the row exists.
Future<int> delete(int id) async {
Database db = await instance.database;
return await db.delete(table, where: '$columnId = ?', whereArgs: [id]);
}
Future<int> deleteContact(int id) async {
Database db = await instance.database;
return await db.delete(tableContact, where: '$columnId = ?', whereArgs: [id]);
}
}
DataBase Item Model
class DatabaseInsetItemModel{
String? name;
String? lName;
String? mobile;
String? email;
String? cat;
String? profile;
DatabaseInsetItemModel(
{required this.name, required this.lName, required this.mobile, required this.email, required this.cat, required this.profile});
DatabaseInsetItemModel.fromJson(Map<String, dynamic> json) {
name = json['postId'];
lName = json['id'];
mobile = json['name'];
email = json['email'];
cat = json['body'];
profile = json['body'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data[DatabaseHelper.columnName] = name;
data[DatabaseHelper.columnLName] = lName;
data[DatabaseHelper.columnMobile] = mobile;
data[DatabaseHelper.columnEmail] = email;
data[DatabaseHelper.columnCategory] = cat;
return data;
}
}
Show Data on screen
class ShowPostScreen extends StatefulWidget {
ShowPostScreen({Key? key}) : super(key: key);
#override
State<ShowPostScreen> createState() => _ShowPostScreenState();
}
class _ShowPostScreenState extends State<ShowPostScreen> {
final dbHelper = DatabaseHelper.instance;
List<DatabaseInsetItemModel> data = [];
#override
void initState() {
// TODO: implement initState
dbHelper.queryAllRows().then((value) {
setState(() {
data = value.map((e) => DatabaseInsetItemModel.fromJson(e)).toList();
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
return Text(data[index].name ?? "");
},
),
);
}
}

How to save list data in SharedPreferences flutter

I make data connection with database to bring a list of data such as the following code:
var listDATA = [];
Future listDATAs() async {
api = '*************';
var response = await http.post(Uri.parse(api));
var responsebody = jsonDecode(response.body);
if (responsebody.length >0){
for (int i = 0; i < responsebody.length; i++) {
listDATA.add(responsebody[i]['name']+ ':' + responsebody[i]['image'].toString());
}
return responsebody;
}else{
}
}
How can I store listDATA in Shared Preferences I need to save name and image ? Then recall it to display after storage
It's preferred not to store non-primitive data types in SharedPreferences as it supports only primitive data types by default. But still there is a way to do it.
you can store the response body of your API call without decoding JSON to a String value.
// Obtain shared preferences.
final prefs = await SharedPreferences.getInstance();
// Save an String value to 'response' key.
await prefs.setString('response', response.body);
if you have response types of List, you can use setStringList method
await prefs.setStringList('items', <String>['Earth', 'Moon', 'Sun']);
in this way you can store list value in shared preference
static setListValue(String key, List< ProductsModel > value) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString(key, jsonEncode(value.map((e) => e.toJson()).toList()));
}
her I make a standard method to store list values from any class by calling
setListValue('store_list', listData);
after that, you have to make a method for getting this list value
//getListValue
static Future<List<ProductsModel>?> getListValue(String key) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
final dataMap = jsonDecode(prefs.getString(key) ?? '[]') as
List<dynamic>;
return dataMap.map<ProductsModel>((item) {
return ProductsModel.fromJson(item);
}).toList();
}
after that, you can call this method like this
var listValue = await SPUtils.getListValue('store_list');
// for saving the list in shared preferences
final prefs = await SharedPreferences.getInstance();
prefs.setString("list",jsonEncode(listDATA));
// for getting the list from shared preferences
final prefs = await SharedPreferences.getInstance();
List listDATA = jsonDecode(prefs.get("list"));
You can follow those steps.
convert your object to map with toMap() method.
encode your map to string with encode() method.
Save the string to shared preferences.
final SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString('key', encodedData);
// Fetch and decode data
final String musicsString = await prefs.getString('musics_key');
Example :
import 'dart:convert';
void main() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final String encodedData = Music.encode([
Music(id: 1, ...),
Music(id: 2, ...),
Music(id: 3, ...),
]);
await prefs.setString('musics_key', encodedData);
// Fetch and decode data final String musicsString = await prefs.getString('musics_key');
final List<Music> musics = Music.decode(musicsString); }
class Music {
final int id;
final String name,
size,
rating,
duration, img; bool favorite;
Music({
this.id,
this.rating,
this.size,
this.duration,
this.name,
this.img,
this.favorite, });
factory Music.fromJson(Map<String, dynamic> jsonData) {
return Music(
id: jsonData['id'],
rating: jsonData['rating'],
size: jsonData['size'],
duration: jsonData['duration'],
name: jsonData['name'],
img: jsonData['img'],
favorite: false,
); }
static Map<String, dynamic> toMap(Music music) => {
'id': music.id,
'rating': music.rating,
'size': music.size,
'duration': music.duration,
'name': music.name,
'img': music.img,
'favorite': music.favorite,
};
static String encode(List<Music> musics) => json.encode(
musics
.map<Map<String, dynamic>>((music) => Music.toMap(music))
.toList(),
);
static List<Music> decode(String musics) =>
(json.decode(musics) as List<dynamic>)
.map<Music>((item) => Music.fromJson(item))
.toList(); }

Save a List to SharedPreferences

I am trying to save the list dragged from the sql to be saved in SharedPreferences, I tried using this code:
static Future<List<User>> getUsers() async {
final myUserId = await getUser();
try {
var myUser = myUserId;
var map = Map<String, dynamic>();
map['user'] = myUser;
final response = await http.post(ROOT, body: map);
//print('getUsers Response: ${response.body}');
//print(myUser);
if (200 == response.statusCode) {
List<User> listContacts = parseResponse(response.body);
SharedPreferences contacts = await SharedPreferences.getInstance();
contacts.setStringList('contacts', listContacts);
return listContacts;
} else {
return List<User>();
}
} catch (e) {
return List<User>(); // return an empty list on exception/error
}
}
the User class for the list is the following:
class User {
final String firstName;
final String lastName;
final String imageLink;
User({this.firstName, this.lastName, this.imageLink});
factory User.fromJson(Map<String, dynamic> json) {
return User(
firstName: json['firstName'] as String,
lastName: json['lastName'] as String,
imageLink: json['imageLink'] as String,
);
}
}
So basically the data is successfully pulling it out from the database, and it does display it, but I want to save the data to SharedPreferences so it doesn't have to load every single time. The error that is occurring is that the listContacts can't be assigned to setStringList, since it is a List<User> and not a List<String>, but I don't know how else can I change the code in order to be able to set the SharedPreferences.
Here you can do is
static Future<List<User>> getUsers() async {
final myUserId = await getUser();
try {
var myUser = myUserId;
var map = Map<String, dynamic>();
map['user'] = myUser;
final response = await http.post(ROOT, body: map);
//print('getUsers Response: ${response.body}');
//print(myUser);
if (200 == response.statusCode) {
List<User> listContacts = parseResponse(response.body);
SharedPreferences contacts = await SharedPreferences.getInstance();
contacts.setString('contacts',json.encode(response.body)); //Here saved the response
return listContacts;
} else {
return List<User>();
}
} catch (e) {
return List<User>(); // return an empty list on exception/error
}
}
Now to fetch it I can use is
SharedPreferences contacts = await SharedPreferences.getInstance();
var response = json.decode(contacts.getString('contacts'));
List<User> listContacts = parseResponse(response.body);
and you get back your data from shared preferences

About Firebase real time database

I am working on Firebase real time databases in Flutter. I am storing user information and their corresponding data in database. My code is given below:
//User Auth Class
class UserAuth{
final String id;
final String email;
final String token;
UserAuth({#required this.id, #required this.email, #required this.token});
}
//User Details Class for storing data of corresponding user
class UserDetails{
final String userDetailsId;
final String name;
final String email;
UserDetails({#required this.userDetailsId,#required this.name, #required this.email});
}
//I am using this code to add userDetails in database.
List<UserDetails> _detailsList = [];
UserDetails _details;
Future<bool> addUserDetails(String username, String email) async {
_isLoading = true;
notifyListeners();
final Map<String, dynamic> userDetails = {
'username': username,
'email': email,
};
try {
final http.Response response = await http.post(
'https://intro-to-firebase-711d4.firebaseio.com/Users.json',
body: json.encode(userDetails));
if (response.statusCode != 200 && response.statusCode != 201) {
_isLoading = false;
notifyListeners();
return false;
}
final Map<String, dynamic> responseData = json.decode(response.body);
_details = UserDetails(
userDetailsId: responseData['name'], name: username, email: email);
_detailsList.add(_details);
_isLoading = false;
notifyListeners();
return true;
} catch (error) {
_isLoading = false;
notifyListeners();
return false;
}
}
Now I want to get the following highlighted ids of the user so how to fetch it. I am using scoped model as a state management in Flutter.
I did it with javascript so far but in the documentation it seems not taht different for flutter:
private void writeNewUser(String userId, String name, String email) {
User user = new User(name, email);
mDatabase.child("users").child(userId).setValue(user);
}
https://firebase.google.com/docs/database/android/read-and-write?authuser=0
This is the example shown in the docs. with .child('users') you can get the right section .child(userId) gives you access to the values.
All you have to do now is defining the variable userId
flutter
you can achieve this as follows
stream: FirebaseDatabase.instance
.reference()
.child('users')
.equalTo(userId)
.onValue,

Create Json Arrays and List with SharedPreferences

I have been using shared_preferences to create and write in Json Files. The Problem i facing is i dont know how to create a Json Array and a List in shared_preferences.
I want to save and read a Json List.
read(String key) async {
final prefs = await SharedPreferences.getInstance();
return json.decode(prefs.getString(key));
}
save(String key, value) async {
final prefs = await SharedPreferences.getInstance();
prefs.setString(key, json.encode(value));
}
remove(String key) async {
final prefs = await SharedPreferences.getInstance();
prefs.remove(key);
}
} ```
Example on DartPad.
Save a list to SharedPreferences with setStringList:
const String key = "users";
List<User> users = [User(name: "tester")];
List<String> jsonList = users.map((user) => user.toJson()).toList();
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setStringList(key, jsonList);
Read a list from SharedPreferences with getStringList:
jsonList = prefs.getStringList(key);
users = jsonList.map((json) => User.fromJson(json)).toList();
The user class with json convert: JSON and serialization
class User {
String name;
int age;
User({
this.name,
this.age,
});
factory User.fromJson(String str) => User.fromMap(json.decode(str));
String toJson() => json.encode(toMap());
factory User.fromMap(Map<String, dynamic> json) => User(
name: json["name"],
age: json["age"],
);
Map<String, dynamic> toMap() => {
"name": name,
"age": age,
};
}
Just map your json array to List<String> and after you can use the setStringList function provided in shared_preferences.dart
/// Saves a list of strings [value] to persistent storage in the background.
///
/// If [value] is null, this is equivalent to calling [remove()] on the [key].
Future<bool> setStringList(String key, List<String> value) =>
_setValue('StringList', key, value);