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(); }
Related
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 ?? "");
},
),
);
}
}
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();
}
so basically this is my provider, what i want is how can i store the model data coming from provider to a shared preferences, and then how to decode it to show it in a bookmark page?
class bookmark extends ChangeNotifier{
int _count = 0;
List<bookmarkModel> bookM = [];
void addCount(){
_count++;
notifyListeners();
}
void addItems(bookmarkModel i){
bookM.add(i);
notifyListeners();
}
int get count => _count;
List<bookmarkModel> get bookMList => bookM;
}
here is my model:
import 'package:flutter/cupertino.dart';
class bookmarkModel{
String title;
String subtitle;
int num;
bookmarkModel({this.title, this.subtitle, this.num});
bookmarkModel.fromJson(Map<String,dynamic> json) :
title = json['title'],
subtitle = json['sutitle'],
num = json['num'];
Map<String, dynamic> toJson()=>{
'title':title,
'subtitle':subtitle,
'num': num
};
}
SharedPreferences should only be used to store small and simple values. It's not meant to be used as a Database.
You can use sharedPreferences to store bool, String, int and simple Lists (not lists of objects or maps). As far as I know, it even cannot store doubles.
Try using a SQflite or Hive (No-SQL) to store more complex or extensive data locally.
You already have toJosn and fromJson ready to use, you just need to convert bookM to a map josnEnode() and the get it back using josnDecode().
try the code below:
void saveBookmark() async{
SharedPreferences prefs = await SharedPreferences.getInstance();
final String List = jsonEncode(bookM, toEncodable: (c)=> c.toJson());
await prefs.setString('BookMarkList', List);
}
void loadBookMark() async{
SharedPreferences prefs = await SharedPreferences.getInstance();
final String saved = prefs.getString('BookMarkList');
final List<dynamic> decoded = jsonDecode(saved);
bookM = decoded.map((bookmark) => bookmarkModel.fromJson(bookmark));
}
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);
I want to store an object in shared preferences which contains some fields in it like name, age, phone number etc. I don't know how to store an object in shared preferences in flutter.
You can Store an object in shared preferences as Below:
SharedPreferences shared_User = await SharedPreferences.getInstance();
Map decode_options = jsonDecode(jsonString);
String user = jsonEncode(User.fromJson(decode_options));
shared_User.setString('user', user);
SharedPreferences shared_User = await SharedPreferences.getInstance();
Map userMap = jsonDecode(shared_User.getString('user'));
var user = User.fromJson(userMap);
class User {
final String name;
final String age;
User({this.name, this.age});
factory User.fromJson(Map<String, dynamic> parsedJson) {
return new User(
name: parsedJson['name'] ?? "",
age: parsedJson['age'] ?? "");
}
Map<String, dynamic> toJson() {
return {
"name": this.name,
"age": this.age
};
}
}
After searching a lot of articles here you are
For saving data to SharedPreferences instance, object must be converted to JSON:
SharedPreferences prefs = await SharedPreferences.getInstance();
Map<String, dynamic> user = {'Username':'tom','Password':'pass#123'};
bool result = await prefs.setString('user', jsonEncode(user));
For getting data from SharedPreferences instance, object must converted from JSON:
String userPref = prefs.getString('user');
Map<String,dynamic> userMap = jsonDecode(userPref) as Map<String, dynamic>;
To Save the object to Shared Preferences
SharedPreferences pref = await SharedPreferences.getInstance();
Map json = jsonDecode(jsonString);
String user = jsonEncode(UserModel.fromJson(json));
pref.setString('userData', user);
To Fetch the object from Shared Preferences
SharedPreferences pref = await SharedPreferences.getInstance();
Map json = jsonDecode(pref.getString('userData'));
var user = UserModel.fromJson(json);
You will need to import below mentioned packages
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
Easiest way to create Model
Follow this answer -> https://stackoverflow.com/a/58708634/9236994
You need to serialize it to JSON before saving and deserialize after reading
See https://flutter.io/docs/development/data-and-backend/json for details
When Getting Data from the API and Saving it Into Sharepreference
Future<UserDetails> UserInfo({String sesscode, regno}) async{
await Future.delayed(Duration(seconds: 1));
SharedPreferences preferences = await SharedPreferences.getInstance();
var map = new Map<String, String>();
map["sesscode"] = sesscode;
map["regno"] = regno;
var response = await http.post(Base_URL().user_info, body: map);
Map decodedata = json.decode(response.body);
if(decodedata != null){
String user = jsonEncode(UserDetails.fromJson(decodedata));
preferences.setString(SharePrefName.infoPref, user);
return UserDetails.fromJson(decodedata);
}
return null;
}
I Create A function for Getting the Details
You can call this function anywhere in your App
Future<UserDetails> getSavedInfo()async{
SharedPreferences preferences = await SharedPreferences.getInstance();
Map userMap = jsonDecode(preferences.getString(SharePrefName.infoPref));
UserDetails user = UserDetails.fromJson(userMap);
return user;
}
Now, Am calling it inside a Class to get username
Future<UserDetails> usd = getSavedInfo();
usd.then((value){
print(value.surname);
});
SharePreferences Handler
I have created a LocalStorageRepository class, that is responsible to handle local data using SharedPreferences.
The class is dynamic and can work with any type of data (int, double, bool, String, and Object) using generics and JSON decoding and encoding.
In order to prevent pron errors, I added the LocalStorageKeys enum to handle the supported keys. Feel free to add more keys to that enum.
enum LocalStorageKeys { tutorialCompleted, user }
#singleton
class LocalStorageRepository {
const LocalStorageRepository(SharedPreferences prefs) : _prefs = prefs;
final SharedPreferences _prefs;
bool keyExists(String key) => _prefs.containsKey(key);
T? getValue<T>(
LocalStorageKeys key, [
T Function(Map<String, dynamic>)? fromJson,
]) {
switch (T) {
case int:
return _prefs.getInt(key.name) as T?;
case double:
return _prefs.getDouble(key.name) as T?;
case String:
return _prefs.getString(key.name) as T?;
case bool:
return _prefs.getBool(key.name) as T?;
default:
assert(fromJson != null, 'fromJson must be provided for Object values');
if (fromJson != null) {
final stringObject = _prefs.getString(key.name);
if (stringObject == null) return null;
final jsonObject = jsonDecode(stringObject) as Map<String, dynamic>;
return fromJson(jsonObject);
}
}
return null;
}
void setValue<T>(LocalStorageKeys key, T value) {
switch (T) {
case int:
_prefs.setInt(key.name, value as int);
break;
case double:
_prefs.setDouble(key.name, value as double);
break;
case String:
_prefs.setString(key.name, value as String);
break;
case bool:
_prefs.setBool(key.name, value as bool);
break;
default:
assert(
value is Map<String, dynamic>,
'value must be int, double, String, bool or Map<String, dynamic>',
);
final stringObject = jsonEncode(value);
_prefs.setString(key.name, stringObject);
}
}
}
In case you want to get an Object value from LocalStorageRepository, you will need to provide its fromJson decoder.
final user = _localStorage.getValue(LocalStorageKeys.user, User.fromJson);
Hope that hence example will help others out there.
Feel free to edit this question and suggest any changes.
If you are getting you data from an API, what you initially get from an API endpoint is a String so you can store the data as a raw String and when you need it you can deserialize it and use where you want to use it
https://gist.github.com/k1ycee/33bb7e51dac81093f949bbd30d7d0dc9
Something like this, the drawback I feel is that if the JSON string data is much might not be advisable to store all the string rather deserialize it and take the ones you deem necessary.