GetStorage always returns null in flutter - android

Code
print("Before : ${GetStorage().read("XXX")}");
GetStorage().write("XXX", 1);
print("After : ${GetStorage().read("XXX")}");
This is my Code. Every time I run the App, the Output is
Before : null
After : 1
Why is the storage data getting cleared everytime I restart the App? I thought this was an alternative to SharedPreference which works just fine. Have I missed something?

Before anything, initialize the package, normally I do this on main.dart
main() async {
await GetStorage.init();
}
Create an instance from GetStorage, I always put a name on the box, if not it will put "GetStorage" by default. It needs to have a name so it can retrieve your data.
GetStorage getStorage = GetStorage('myData');
After that you can write and retrieve data from it, I recommend you to "await" all reads and writes.
await getStorage.write('XXX', 1);
var a = await getStorage.read('XXX');
print(a); /// 1
I recommend you to put a name on the box according to what you are storing.

You should await for GetStorage.init().
void main() async {
await GetStorage.init();
print("Before : ${GetStorage().read("XXX")}");
GetStorage().write("XXX", 1);
print("After : ${GetStorage().read("XXX")}");
}

final _userBox = () => GetStorage('User');
class UserPref {
void call(){
_userBox.call()..initStorage;
}
dynamic setValueInt(String key, int value) {
return 0.val(key, getBox: _userBox).val = value;
}
String setValue(String key, String value) {
return ''.val(key, getBox: _userBox).val = value;
}
dynamic getValueInt(String key) {
return (-1).val(key,getBox: _userBox).val;
}
dynamic getValue(String key) {
return ''.val(key,getBox: _userBox).val;
}
void setUser(User user) {
''.val('uname', getBox: _userBox).val = user.uname ?? '';
(-1).val('gender', getBox: _userBox).val = user.gender ?? -1;
''.val('born', getBox: _userBox).val = user.born.toString();
true.val('enabled', getBox: _userBox).val = user.enabled ?? true;
}
User getUser() {
final String? uname = ''.val('uname',getBox: _userBox).val;
final int? gender = (-1).val('gender',getBox: _userBox).val;
final DateTime? born = ''.val('born',getBox: _userBox).val == '' ? null : DateTime.parse(''.val('born',getBox: _userBox).val);
final bool? enabled = true.val('enabled',getBox: _userBox).val;
return User(
uname: uname,
gender: gender,
born: born,
enabled: enabled,
);
}
}
///INIT:
#override
void initState() {
//The init function must be written separately from the read/write function due to being asynchronous.
UserPref().call();
}
//OR
Future<void> main() async {
//await GetStorage.init();
UserPref().call();
}
///USAGE:
class MyStatefulWidget extends StatefulWidget {
final Users prefUser = UserPref().getUser();
...
}
//OR
#override
Widget build(BuildContext context) {
final Users prefUser = UserPref().getUser();
return ...;
}

Related

Flutter http get request json serialization

I would like to make a get requests and to convert results to a list of objects.
Actually i did that :
post_model.dart
#JsonSerializable()
class Post {
Post({
required this.userId,
required this.id,
required this.title,
required this.body,
});
factory Post.fromJson(Map<String, dynamic> json) => _$PostFromJson(json);
Map<String, dynamic> toJson() => _$PostToJson(this);
final int userId;
final int id;
final String title;
final String body;
}
http_service.dart :
class HttpService {
final String url = 'https://jsonplaceholder.typicode.com';
final String postsURL = '/posts';
final Map<String, String> headers = {
'Content-Type': 'application/json'
};
List<Post> parsePosts(String responseBody) {
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Post>((json) => Post.fromJson(json)).toList();
}
Future<List<Post>> fetchPosts() async {
final http.Response response = await http.get(Uri.https(url, postsURL));
if (response.statusCode == 200) {
return compute(parsePosts,response.body);
} else {
throw Exception("Failed to load posts ${response.statusCode}");
}
}
}
But i encouter all in red on the parsePosts method.
On the final parsed :
Missing variable type for 'parsed'.
Try adding an explicit type, or remove implicit-dynamic from your analysis options file.dart(implicit_dynamic_variable)
and on the return :
A value of type 'dynamic' can't be returned from the method 'parsePosts' because it has a return type of 'List<Post>'
I just don't understand what i'm doing wrong, because i have follow the flutter doc here :
https://flutter.dev/docs/cookbook/networking/background-parsing
Thanks for any help
Some time ago I did this code for that API:
import 'dart:async';
import 'package:wnetworking/wnetworking.dart';
class Post {
int? userId, id;
String? title, body;
Post.fromJson(Map<String, dynamic> data) {
userId = data['userId'];
id = data['id'];
title = data['title'];
body = data['body'];
}
}
class JsonPlaceHolder {
static const baseUrl = 'https://jsonplaceholder.typicode.com';
/* ---------------------------------------------------------------------------- */
static FutureOr<void> _doGet(String path, {void doThis(var response)?}) async {
await HttpReqService.getJson(baseUrl + path)
.then((response) => doThis == null ? print(response) : doThis(response))
.whenComplete(() => print('\nFetching done!'));
}
/* ---------------------------------------------------------------------------- */
static FutureOr<void> _doPost(String path, {required Object body, int okCode = 200}) async {
await HttpReqService.post<Map<String, dynamic>>(baseUrl + path, body: body, okCode: okCode)
.then((response) => print(response))
.whenComplete(() => print('\nPost sent successfully'));
}
/* ---------------------------------------------------------------------------- */
static FutureOr<void> fetchPosts({int? id, bool onlyComments = false, bool useObjList = false}) async {
var path = '/posts/${id ?? ''}';
if (id != null && onlyComments) path += '/comments';
useObjList
? await _doGet(path, doThis: (response) {
if (response != null) {
print((response as List).map<Post>((m) => Post.fromJson(m as Map<String, dynamic>)));
}
})
: await _doGet(path);
}
/* ---------------------------------------------------------------------------- */
static FutureOr<void> fetchComments([int? postId]) => _doGet('/comments${postId != null ? '?postId='+postId.toString() : ''}');
static FutureOr<void> fetchAlbums() => _doGet('/albums');
static FutureOr<void> fetchPhotos() => _doGet('/photos');
static FutureOr<void> fetchTodos() => _doGet('/todos');
static FutureOr<void> fetchUsers() => _doGet('/users');
}
void main(List<String> args) async {
// await JsonPlaceHolder.fetchComments(1);
await JsonPlaceHolder.fetchPosts(useObjList: true);
print('Finished!');
}
Result:
(Instance of 'Post', Instance of 'Post', Instance of 'Post', ..., Instance of 'Post', Instance of 'Post')
Fetching done!
Finished!
Note
wnetworking package is not ready to publish yet, it contains operations related to API, etc. You can replace HttpReqService.getJson and HttpReqService.post with your typical http.get and http.post respectively but keep in mind the return value and exceptions.
Use Uri.parse
Those errors are due to a dart version.
A fix has been made by another user on github : https://github.com/flutter/website/pull/5798
Following this PR, it's works

cant save json.decode to share preferences in flutter

I have list, I want to save in sharepreferences,
setString('key',json.encode(temporaryData));
When I try to get this value, only show Instance of Future<dynamic>
but when i print that json.encode show it value
[{"name":"Stranger","birthDate":"","idCardNum":"-1","currentTime":1593598133479,"imageFlag":1,"imageName":"-1_1_1593598133479.png","type":-1,"tempratrue":"36.3","mask":0}]
Future<SharedPreferences> storage() {
return SharedPreferences.getInstance();
}
void setTempData(String temp) async {
SharedPreferences sharedPreferences = await storage();
await sharedPreferences.setString('datas', temp);
}
getTempData(String key) async {
SharedPreferences sharedPreferences = await storage();
await sharedPreferences.get(key);
}
_getTemp() async {
DateTime start = DateTime.now().subtract(Duration(seconds: 5));
DateTime end = DateTime.now();
Map data = {'pass': '123456', 'startTime': '$start', 'endTime': '$end'};
var response = await http.post('$urlApiQr:8080/newFindRecords', body: data);
var jsonData = json.decode(response.body);
var jsEnc = json.encode(response.body);
TempJson tempJson = TempJson.fromJson(jsonData);
var parse = json.decode(tempJson.config);
setState(() {
dataList = parse;
temporaryData = dataList.toSet().toList();
setTempData(json.encode(temporaryData));
//try to print value
print('$start and $end');
print(parse);
print(getTempData('datas'));
});
}
Is there a solution to my problem?
UPDATE 2.0
you have to add await anywhere your are requesting value from a Future.. as the below method return a Future as you can see from your error, just add await keyword from where you are requesting a value,
for example
print(await getTempData(key));
UPDATE
return keyword missing
getTempData(String key) async {
SharedPreferences sharedPreferences = await storage();
//you missed the return keyword here
return await sharedPreferences.get(key);
}
original answer
dont miss the await keyword
var thestring = await sp.getString('the_key');
var theJsonObj = json.decode(thestring);
this is my assumption, please post more code

Flutter how to get a Future<bool> to a normal bool type

Hi I'm trying to get a Future to be used as a normal boolean, how do I use this function as the determiner for a normal boolean without it giving me an incorrect type error?
Future<bool> checkIfOnAnyChats() async {
FirebaseUser user = await _auth.currentUser();
final QuerySnapshot result = await _firestore
.collection('chats')
.where('members', arrayContains: _username)
.getDocuments();
final List<DocumentSnapshot> documents = result.documents;
if(documents.length > 0) {
return Future<bool>.value(true);
}else{
return Future<bool>.value(false);
}
}
How do I apply it to a normal type boolean and not get this error? Thanks.
you don't need to convert bool into future, as you are in async method it will return future only.
you can get that value in initstate, you can not get value outside any method.
bool _isInChat;
#override
void initState() {
super.initState();
CheckIfOnAnyChats().then((value){
SetState((){
_isInChat = value;
});
});
}

How to return Future<object> and assign it to just object , flutter

I have a custom class that fetches data from the database, that returns Future<List<Line>>, which lies in line_list.dart files :
Future<List<Line>> fetchingLinesData() async {
List<Line> lineList = [];
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'main.db');
Database database = await openDatabase(path, version: 1);
database.transaction((tnx) async {
dbRef.child('line').once().then((DataSnapshot dataSnapshot) async {
dataSnapshot.value.forEach((key, value) async {
List<Station> inLineStations = [];
for (var i = 0; i < 100; i++) {
if (value["station_$i"] != null) {
List<Map> stations = await tnx.rawQuery("SELECT * FROM Station");
stations.forEach((s) {
if (s['stationName'] == value["station_$i"]) {
Station stationInstance = Station(
key: s['key'],
cityName: s['cityName'],
stationName: s['stationName'],
stationLongitude: s['stationLongitude'],
stationLatitude: s['stationLatitude']);
inLineStations.add(stationInstance);
}
});
}
}
Line lineInstance = Line(
startStation: value['start_station'],
endStation: value['end_station'],
inLineStations: inLineStations,
notes: value['notes'],
price: value['price'],
transportationType: value['transportation_type']);
lineList.add(lineInstance);
});
});
});
return lineList;
}
}
and then in my main.dart widget, I have this :
List<Line> allLines = [];
I want to do something like this :
allLines = LinesList().fetchingLinesData();
But of course, it gives me an error as am trying to assign Future<List<Line>> to List<Line>
how to do it?
You have to await for future to complete.
allLines = await LinesList().fetchingLinesData();
You would just put the code below in a async function make main async and make your code
allLines = await LinesList().fetchingLinesData();

How hold the splash screen till data are ready

Is it possible that the spash screen (launch screen)
is shown till the data needed for the app is ready?
Are there other options in manifest.xml as below?
"io.flutter.app.android.SplashScreenUntilFirstFrame"
After many retries I found a solution which could be optimized.
Please tell me your opinion
Normally flutter starts with
void main() => runApp(new MyApp());
I inserted the data acquisition on the begin by modifying the code
void main() async {
final OrderedAppList aList = new OrderedAppList(); //class to get all data
var funx = (int) async => aList.getit(); //to get all of the data
var value;
value = await funx(1); //should wait for the return value
runApp(new MyApp(
qallUserApps: aList.allUserApps,
qlistLen: value, // means aList.listLen,
qplatformVersion: aList.platformVersion,
qmodel: aList.model
));
}
And in MyApp:
class MyApp extends StatelessWidget {
final List qallUserApps;
final int qlistLen;
final String qplatformVersion;
final String qmodel;
// Constructor:
const MyApp({Key key, this.qallUserApps,
this.qlistLen,
this.qplatformVersion,
this.qmodel})
: super(key: key);
#override
Widget build(BuildContext context) {
// ...
}
Code part of the class OrderedAppList:
class OrderedAppList {
int listLen= -1;
String platformVersion = "Unknown Platform";
String model = "Unknown Platform";
List allUserApps = null;
Future<int> getit() async {
try {
allUserApps = await AppsAsStateless.allApps;
listLen = allUserApps.length;
} on Exception {
allUserApps = null;
listLen = 0;
}
// ...
return listLen ;
}
Thanks for reading this!
it works fine and
the code in main can be optimized:
void main() async { // async that data acquisition done before any widgets shown
final OrderedAppList aList = new OrderedAppList();
int value;
value = await aList.getit();
runApp(new MyApp(
qallUserApps: aList.allUserApps,
qlistLen: value, // = aList.listLen,
qplatformVersion: aList.platformVersion,
qmodel: aList.model
));
}

Categories

Resources