0

Hello Iam a newbie in Flutter and i need help.

My use case is, i have a UserClass, a SharedPreferencesModel and a DashboardScreen with UserData fetch from the internet. But UserData is stored in cache and by call the Function 'loadUser' with the 'readData'-Function from the SharedPreferencesModel inside, no filled the object User from the UserClass...

Here the UserClass:

class User {
  final String firstname;
  final String lastname;
  final String club;
  final String year;
  final String gender;

  User({this.firstname, this.lastname, this.year, this.club, this.gender});

  factory User.fromJson(Map<String, dynamic> json) {
    return new User(
        firstname: json['firstname'],
        lastname: json['lastname'],
        year: json['year_of_birth'],
        club: json['club'],
        gender: json['gender']);
  }

  Map<String, dynamic> toJson() {
    return {
      'firstname': this.firstname,
      'lastname': this.lastname,
      'club': this.club,
      'year_of_birth': this.year,
      'gender': this.gender,
    };
  }
}

Here is my SharedPreferencesModel:

import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';

class SharedPreferencesModel {
  // save
  storeData(String key, value) async {
    final preferences = await SharedPreferences.getInstance();
    await preferences.setString(key, jsonEncode(value));
  }

  // read
  readData(String key) async {
    final preferences = await SharedPreferences.getInstance();
    return jsonDecode(preferences.getString(key));
  }

  // remove
  deleteData(String key) async {
    final preferences = await SharedPreferences.getInstance();
    preferences.remove(key);
  }
}

Here is a Snippet of the Widget:

SharedPreferencesModel data = new SharedPreferencesModel();
  User userDataLoad = new User();

  loadUser() async {
    try {
      // Data are displayed as json in the debugging-terminal
      print(await data.readData("user"));

      // something its wrong here
      User user = User.fromJson(await data.readData("user"));

      // "Test 2" is not displayed
      print("Test 2");

      Scaffold.of(context).showSnackBar(SnackBar(
          content: new Text('Daten werden geladen...'),
          duration: const Duration(milliseconds: 1000)));
      userDataLoad = user;
    } catch (Exception) {
      Scaffold.of(context).showSnackBar(SnackBar(
          content: new Text('Keine Daten gefunden!'),
          duration: const Duration(milliseconds: 1000)));
    }
  }

  void initState() {
    super.initState();
    loadUser();
    // only for testing
    print("test 1");
  }

  @override
  Widget build(BuildContext context) {
    ...

Thanks for any help!

  • To be honest, I did not really understand what your problem is. But at first glance, none of your `async` functions return a `Future`, that means whatever you are doing, *cannot* work correctly. Please fix that first, then test if your problem is already gone and if it still persists, please post your updated code and a good, step by step description of your problem. – nvoigt Sep 03 '20 at 07:03
  • @nvoigt Ok, I do that. Thanks a lot! –  Sep 03 '20 at 07:09
  • Also, since you are not saving the Future from loadUser() or using `setState` yourself, your function might run, but it will not show any results, because your build will not run again. See https://stackoverflow.com/questions/63017280/what-is-a-future-and-how-do-i-use-it for more on that. – nvoigt Sep 03 '20 at 07:09
  • 1
    @nvoigt Yes, that is exactly the fault. I thought, I could bypass the FutureBuilder. –  Sep 03 '20 at 08:18

2 Answers2

0

[SOLVED]

The error was a conversion error.

store the data from response.body as string

try {
    if (response.statusCode == 200) {
      return _data.storeData("user", response.body); <<<<< 
    } else {
      throw Exception('Get Fail!');
    }
  } catch (error) {
    throw Exception(error);
  }

here the function storeData with save data as string in string very bad fail

class SharedPreferencesModel {
  // save
  storeData(String key, value) async {
    final preferences = await SharedPreferences.getInstance();
    await preferences.setString(key, jsonEncode(value));  <<<<<<<<<<<<<
  }

here the solution save only value

class SharedPreferencesModel {
  // save
  storeData(String key, value) async {
    final preferences = await SharedPreferences.getInstance();
    await preferences.setString(key, value);  <<<<<<<<<<<<< 
  }

Thanks for help!

-1

Here:

  readData(String key) async {
    final preferences = await SharedPreferences.getInstance();
    return jsonDecode(preferences.getString(key));
  }

You're now basically passing a Future object as a parameter to your jsonDecode function. I guess you need to put an await before preferences.getString(key) cause it's a future. So it would be the following:

  readData(String key) async {
    final preferences = await SharedPreferences.getInstance();
    return jsonDecode(await preferences.getString(key));
  }
Parsa
  • 103
  • 1
  • 7
  • 1
    No. `getString` returns a `String`, not a `Future`. It would not have compiled otherwise anyway. – nvoigt Sep 03 '20 at 07:41