3

UPDATE: Thanks to @Rjulcaa answer My map is now a List, however the List wasn't displayed on the UI. I turns that I needed to handle the future with a FutureBuilder, so in case anyone faces this problem remember to add a FutureBuilder to the body of your UI and on the builder return the widget you want to be displayed.

I'm making a todo list tutorial, I'm trying to add the feature of encoding on a JSON my todoList the save it on a sharedPreferences, and when I start the app retrieve it on the screen

This is my TODO class

class Todo  {
Todo ({this.title,this.isDone = false});
String title;
bool isDone;


//Decode method to convert a Json String into a Dynamic object
Todo.fromJson(Map <String, dynamic> json)
: title = json ["title"],
  isDone  = json ["isDone"];
Map <String,dynamic> toJson() =>
{
       "title" : title,
       "isDone" : isDone
};
}

This is my screen

class _TodoListScreenState extends State<TodoListScreen> {
List<Todo> todos = [];
@override
void initState() {
super.initState();
 _getTodoFromSharedPreferences();

}



//updates the state of the checkbox and reflects it on the UI
_toggleTodo(Todo todo, bool isChecked) {
setState(() {
  todo.isDone = isChecked;
});
}

_addTodo() async {
final todo = await showDialog<Todo>(
  context: context,
builder:(BuildContext context) { // <- Here you draw the Dialog
  return NewTodoDialog();
},
);
if (todo != null) {
  setState(() {
    todos.add(todo);
    _saveTodo(todos);
    print(todos.length);

    });
   }
   }

   _saveTodo(List<Todo> todo) async{
   final String newTodo = jsonEncode(todo);
   setSharedPreferences(newTodo);
   }



    _getTodoFromSharedPreferences () async {
    final prefs = await SharedPreferences.getInstance();
    final savedTodo = prefs.getString("savedTodo");
    if (savedTodo == null) {return null;} else {
    Map MapofTodos = jsonDecode(savedTodo);
  for (var i = 0; i < MapofTodos.length; ++i) {
    var o = MapofTodos[i];
    setState(() {
      Todo todo = Todo.fromJson(o);
      todos.add(todo);
    });


  }


}
}
 setSharedPreferences (String newTodo ) async{
 final prefs = await SharedPreferences.getInstance();
 await prefs.setString("savedTodo", newTodo );
 print(newTodo);
 }

 @override
  Widget build(BuildContext context) {
   return Scaffold(
            appBar: AppBar(backgroundColor:Colors.deepPurple[900] ,
               title: Text('Todo List')),
       body: TodoList(
         todos: todos,
         onTodoToggle: _toggleTodo,
       ),
       floatingActionButton: FloatingActionButton(
         backgroundColor: Colors.purpleAccent[700],
         child: Icon(Icons.add),
         onPressed: _addTodo,
       ),
   );
  }


  }

when I run the app i get this error

E/flutter ( 7476): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] 
Unhandled Exception: type 'List<dynamic>' is not a subtype of type 
'Map<dynamic, dynamic>'
E/flutter ( 7476): #0      
_TodoListScreenState._getTodoFromSharedPreferences 
(package:flutter_todo/UI/todo_list_screen.dart:70:11)
E/flutter ( 7476): <asynchronous suspension>
E/flutter ( 7476): #1      _TodoListScreenState.initState 
(package:flutter_todo/UI/todo_list_screen.dart:29:6)
E/flutter ( 7476): #2      StatefulElement._firstBuild 
(package:flutter/src/widgets/framework.dart:3851:58)
E/flutter ( 7476): #3      ComponentElement.mount 
(package:flutter/src/widgets/framework.dart:3716:5)
E/flutter ( 7476): #4      Element.inflateWidget 
(package:flutter/src/widgets/framework.dart:2960:14)
E/flutter ( 7476): #5      Element.updateChild 
(package:flutter/src/widgets/framework.dart:2763:12)
E/flutter ( 7476): #6      SingleChildRenderObjectElement.mount 
(package:flutter/src/widgets/framework.dart:4881:14)
E/flutter ( 7476): #7      Element.inflateWidget 
(package:flutter/src/widgets/framework.dart:2960:14)
E/flutter ( 7476): #8      Element.updateChild 
(package:flutter/src/widgets/framework.dart:2763:12)
E/flutter ( 7476): #9      ComponentElement.performRebuild 
(package:flutter/src/widgets/framework.dart:3752:16)
E/flutter ( 7476): #10     Element.rebuild 
(package:flutter/src/widgets/framework.dart:3564:5)
E/flutter ( 7476): #11     ComponentElement._firstBuild 
(package:flutter/src/widgets/framework.dart:3721:5)
E/flutter ( 7476): #12     ComponentElement.mount 
(package:flutter/src/widgets/framework.dart:3716:5)
E/flutter ( 7476): #13     Element.inflateWidget 
(package:flutter/src/widgets/framework.dart:2960:14)
E/flutter ( 7476): #14     Element.updateChild 
(package:flutter/src/widgets/framework.dart:2763:12)
E/flutter ( 7476): #15     SingleChildRenderObjectElement.mount 
(package:flutter/src/widgets/framework.dart:4881:14)
E/flutter ( 7476): #16     Element.inflateWidget 
(package:flutter/src/widgets/framework.dart:2960:14)
E/flutter ( 7476): #17     Element.updateChild 
(package:flutter/src/widgets/framework.dart:2763:12)
E/flutter ( 7476): #18     SingleChildRenderObjectElement.mount 
(package:flutter/src/widgets/framework.dart:4881:14)
E/flutter ( 7476): #19     Element.inflateWidget 
(package:flutter/src/widgets/framework.dart:2960:14)
E/flutter ( 7476): #20     Element.updateChild 
(package:flutter/src/widgets/framework.dart:2763:12)
E/flutter ( 7476): #21     SingleChildRenderObjectElement.mount 
(package:flutter/src/widgets/framework.dart:4881:14)
E/flutter ( 7476): #22     Element.inflateWidget 
(package:flutter/src/widgets/framework.dart:2960:14)
E/flutter ( 7476): #23     Element.updateChild 
(package:flutter/src/widgets/framework.dart:2763:12)
E/flutter ( 7476): #24     SingleChildRenderObjectElement.mount 
(package:flutter/src/widgets/framework.dart:4881:14)
E/flutter ( 7476): #25     Element.inflateWidget 
(package:flutter/src/widgets/framework.dart:2960:14)
E/flutter ( 7476): #26     Element.updateChild 
(package:flutter/src/widgets/framework.dart:2763:12)
E/flutter ( 7476): #27     ComponentElement.performRebuild 
(package:flutter/src/widgets/framework.dart:3752:16)
E/flutter ( 7476): #28     Element.rebuild 
(package:flutter/src/widgets/framework.dart:3564:5)
E/flutter ( 7476): #29     ComponentElement._firstBuild 
(package:flutter/src/widgets/framework.dart:3721:5)
E/flutter ( 7476): #30     StatefulElement._firstBuild 
(package:flutter/src/widgets/framework.dart:3869:11)
E/flutter ( 7476): #31     ComponentElement.mount 
(package:flutter/src/widgets/framework.dart:3716:5)
E/flutter ( 7476): #32     Element.inflateWidget 
(package:flutter/src/widgets/framework.dart:2960:14)
E/flutter ( 7476): #33     Element.updateChild 
(package:flutter/src/widgets/framework.dart:2763:12)
E/flutter ( 7476): #34     ComponentElement.performRebuild 
(package:flutter/src/widgets/framework.dart:3752:16)
E/flutter ( 7476): #35     Element.rebuild 
(package:flutter/src/widgets/framework.dart:3564:5)
E/flutter ( 7476): #36     ComponentElement._firstBuild 
(package:flutter/src/widgets/framework.dart:3721:5)
E/flutter ( 7476): #37     ComponentElement.mount 
(package:flutter/src/widgets/framework.dart:3716:5)
E/flutter ( 7476): #38     Element.inflateWidget 
(package:flutter/src/widgets/framework.dart:2960:14)
E/flutter ( 7476): #39     Element.updateChild 
(package:flutter/src/widgets/framework.dart:2763:12)
E/flutter ( 7476): #40     ComponentElement.performRebuild 
(package:flutter/src/widgets/framework.dart:3752:16)
E/flutter ( 7476): #41     Element.rebuild 
(package:flutter/src/widgets/framework.dart:3564:5)
E/flutter ( 7476): #42     ComponentElement._firstBuild 
(package:flutter/src/widgets/framework.dart:3721:5)
E/flutter ( 7476): #43     StatefulElement._firstBuild 
(package:flutter/src/widgets/framework.dart:3869:11)
E/flutter ( 7476): #44     ComponentElement.mount 
(package:flutter/src/widgets/framework.dart:3716:5)
E/flutter ( 7476): #45     Ele

I tried to change the List to a Map but didn't succeed

I have succeeded on everything except returning the widget to the screen. Help me, please :c

1
  • try this var todo = Todo.fromJson(o); Commented May 8, 2019 at 19:07

3 Answers 3

0

I faced this problem before because I wanted to save an array object in shared preferences. You can try this.

//Save you array object as an array of Strings in Shared Preferences
 void _saveTodo(List<Todo> todo) async{
  SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
  sharedPreferences.setStringList("savedTodo", _mapTodoData(todo));
 }
}

Transform the JSON into an array of Strings

 List<String> _mapTodoData(List<dynamic> todos) async{
  try {
      var res = todos.map((v) => json.encode(v)).toList();
      return res;
    } catch (err) {
     // Just in case
      return [];
    }
 }
}

if you want to get and transform the data in a List of Todo objects

void loadData() async {

 SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
 final todoArray = _decodeTodoData(sharedPreferences.getStringList("savedTodo"))
 //This is your array :) -> todoArray    
}
List<Todo> _decodeTodoData(List<String> todos) {
    try {
      //Transforming List<String> to Json
      var result = todos.map((v) => json.decode(v)).toList();
      //Transforming the Json into Array<Todo>
      var todObjects = result.map((v) => Todo.fromJson(v)).toList();
      return todObjects;
    } catch (error) {
      return [];
    }
  }
}

This worked for me, I really struggled with this problem.

I Hope this works for you too.

Sign up to request clarification or add additional context in comments.

1 Comment

Hi! thanks for the quick and detailed response, now I'm handling a different problem, I can't use de saveTodo method it tells me ` [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: type 'Future<dynamic>' is not a subtype of type 'List<String>' _TodoListScreenState._saveTodo (package:flutter_todo/UI/todo_list_screen.dart:60:50) and the codeline is this one _mapTodoData(todo)); }`
0

Here you're trying to iterate over a Map which is not possible because only possible Iterables objects are Set,List and Queue.

// Map MapofTodos = jsonDecode(savedTodo); 
//Try to debug it first first and see what type it's returning
print(jsonDecode(savedTodo).runtimeType);

Comments

0

I faced the same issue during app development in dart. The issue with json decoding techniques or might be json conversion. I have done work around for creating the method as passing the parameter as

getCardData(data[0]["cardContent"][0]["cardData"] as List),
  List<String> getCardData(data) {
    List<String> _cardInfo = [];
    for (int i = 0; i < data.length; i++) {
      _cardInfo.add(data[i] as String);
    }
    return _cardInfo;
  }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.