Search code examples
visual-studioflutterdartsharedpreferencesprovider

Flutter/Dart - The method 'setStringList' was called on null


i am new in programming. i try a few simple things but i have a error where i can't get any further. so here is the NoSuchMethodError i got:

The method 'setStringList' was called on null. Receiver: null Tried calling: setStringList("title", Instance(length:1) of '_GrowableList')

I will now show you the code where I think the error is:

import 'dart:collection';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

import 'package:pro_todo/models/task.dart';

class TodosModel extends ChangeNotifier {
  List<Task> _tasks = [];
  SharedPreferences sharedPreferences;

  saveSharedPreferences() async {
    sharedPreferences = await SharedPreferences.getInstance();
    loadData();
  }

  UnmodifiableListView<Task> get allTasks => UnmodifiableListView(_tasks);
  UnmodifiableListView<Task> get incompleteTasks =>
      UnmodifiableListView(_tasks.where((task) => !task.completed));
  UnmodifiableListView<Task> get completedTasks =>
      UnmodifiableListView(_tasks.where((task) => task.completed));

  void addTodo(Task task) {
    _tasks.add(task);
    saveData();
    notifyListeners();
  }

  void toggleTodo(Task task) {
    final taskIndex = _tasks.indexOf(task);
    _tasks[taskIndex].toggleCompleted();
    notifyListeners();
  }

  void deleteTodo(Task task) {
    _tasks.remove(task);
    notifyListeners();
  }

  void saveData() {
    List<String> spList =
        _tasks.map((task) => json.encode(task.toMap())).toList();
    sharedPreferences.setStringList('title', spList);
    print(spList);
  }

  void loadData() {
    List<String> spList = sharedPreferences.getStringList('task');
    _tasks = spList.map((task) => Task.fromMap(json.decode(task))).toList();
    notifyListeners();
  }
}

at void saveData => sharedPreferences.setStringList('title', spList) ist the error. if i mark it as a comment the program didn't gave me any error but it also won't saved the data.

i think to understand the _tasks list you need to see this code:

import 'package:flutter/material.dart';

class Task {
  String title;
  bool completed;

  Task({@required this.title, this.completed = false});

  void toggleCompleted() {
    completed = !completed;
  }

  Task.fromMap(Map map)
      : this.title = map['title'],
        this.completed = map['completed'];

  Map toMap() {
    return {
      'title': this.title,
      'completed': this.completed,
    };
  }
}

and this is the method to call the addTask method:

void onAdd() {
    final String textVal = taskTitleController.text;
    final bool completed = completedStatus;
    if (textVal.isNotEmpty) {
      final Task task = Task(
        title: textVal,
        completed: completed,
      );
      Provider.of<TodosModel>(context, listen: false).addTodo(task);
      Navigator.pop(context);
    }
  }

i hope anyone can help and thank you in advance!


Solution

  • Your instance of SharedPreferences is not initialized when you call your method saveData You must initialize it with sharedPreferences = await SharedPreferences.getInstance(); before setting the list.

      SharedPreferences sharedPreferences;
    
      SharedPreferences  _getSharedPreferences() async {
        if(sharedPreferences == null){
            sharedPreferences = await SharedPreferences.getInstance();
        }
        return sharedPreferences;
      }
    
      void saveData() async {
        List<String> spList =
            _tasks.map((task) => json.encode(task.toMap())).toList();
        _getSharedPreferences().setStringList('title', spList);
        print(spList);
      }
    
      void loadData() {
        List<String> spList = _getSharedPreferences().getStringList('task');
        _tasks = spList.map((task) => Task.fromMap(json.decode(task))).toList();
        notifyListeners();
      }