Flutter - how to store lists of Strings: (GetStorage or Shared Preferences). using android

Viewed 3859

So, I have come across a solution for this problem using Get_storage thanks to a couple of great explanations about the topic. I managed to work with getx and the Provider package to save data when adding new stuff and reading it when starting the application (thats the behavior i'm going for here). Said that, i'm having a hard time trying to remove data from memory.

Context
The project is a to-do list app, the front end is working perfectly, but when it comes to storage it gets more complicated. The thing is that i'm very new to flutter and mobile development, i recieved some help but this kind of stuff is still foggy in my brain, i could not remove data using the same logic. When i called box.Remove('key') like the docs say, my ENTIRE list got removed. I don't have a single clue why that happaned.

And so i wonder if i could understand it more by reading through some more explanations, i know Shared Preferences is a great deal do work with this kind of situation, but i would also be confortable with a solution using get_storage since i'm more familiar with it.

the code:\

I'm calling these lists inside a listView on a different file with the help of Provider - -

List<Task> _tasks = [
Task(
  name: "Title",
  description: "Description",
),

];

Adding tasks to my ListView - -

void add(String newTitle, newDesc) {
    final task = Task(name: newTitle, description: newDesc);
    _tasks.add(task);

    notifyListeners();
  }

Here is the removal of a task from the ListView - -

void removeTasks(Task task) {
_tasks.remove(task);

notifyListeners();

}

I tried to implement a logic to write and read data, it worked. But i also tried to use this removeTasks method to remove from storage as well by calling box.Remove('tasks'); ('tasks' was the key passed to the writing and reading methods). It removed everything from memory since my listview got empty.

Since i'm not that experienced, i went through the documentation and could understand some of the SharedPreferences Explanation (same with got_storage) but i'm having a hard time when trying to apply it to my code.

I would appreciate any help using get_storage OR shared preferences to this problem.

Where i'm calling the deletion:

// bool variables that control the state of the screen
// since i can change it to show done tasks or on goind tasks
// dont mind that, i think its irrelevant to the problem.
// 
bool isActiveDoing = true;
bool isActiveDone = false;

List finalArray = [];  //it will store the tasks

class TaskList extends StatefulWidget {
  @override
  _TaskListState createState() => _TaskListState();
}

class _TaskListState extends State<TaskList> {
  @override
  Widget build(BuildContext context) {
     //dont mind the if else as well, its not part of the problem 
     //just using it to handle the state of the screen
    if (isActiveDoing) {
      finalArray = Provider.of<TasksFunctions>(context).tasks;
    }
    //TasksFunctions is a class with methods on regards to the storage
    //it contains add tasks, remove, etc... i'm using provider to
    //link those to the screens with the notifyListeners
    if (isActiveDone) {
      finalArray = Provider.of<TasksFunctions>(context).doneTasks;
    }

    //now here is where i call the class tha has the deletion method
    return Consumer<TasksFunctions>(
      builder: (context, tasksFunctions, child) {
        return ListView.builder(
          //list view tha has all the tasks
          itemCount: finalArray.length,
          itemBuilder: (context, index) {
            final task = finalArray[index];

 //using the slidableWidget to wrap the deletion method 
            return SlidableWidget(
              onDismissed: (action) {
                if (isActiveDoing) {
                  Provider.of<TasksFunctions>(context, listen: false)
                      .removeTask(task);
//so here is where i'm deleting those tasks, calling that method
//listed up on this post
               
                }
                if (isActiveDone {
                  Provider.of<TasksFunctions>(context, listen: false)
                      .removeDone(task);
                }
              },
             
            );
          },
        );
      },
    );
  }
}

So i spent some time translating the code, but i think that it does not match any of flutter's good practices principles.

I also tried calling storageList.remove(task); and then rewriting it with the box.write('tasks', storageList); but nothing was removed from the memory (maybe because i didn't loop through the whole storageLists searching for the right index i guess)

1 Answers

Sounds like your code is based on my answer to your original question about this.

If that's the case, then the key tasks is the key to the entire list of maps, not a single map or Task. So it's behaving as expected when it wipes all of your tasks.

In order to persist any changes, you'd have to remove that particular map (Task) from storageList then overwrite the box again with box.write('tasks', storageList); It will save over the same list of maps and persist any deletions you made.

If you share your code where you're trying to delete the task and whats going on around it I can give you a more specific example.

EDIT: Answering question in comments.

If you wanted to go the UniqueKey route you wouldn't need the index at all. You could do something like this.

class Task {
  final String name;
  final String description;
  final String key; // not an actual Key but will take the String value of a UniqueKey

  Task({this.key, this.name, this.description});
}

When you add a new Task it would look like this.

final task = Task(
    description: 'test description',
    name: 'test name',
    key: UniqueKey().toString());

Then you could use a Map of maps instead of a list of maps and use the key for both.

  Map storageList = {};

   void addAndStoreTask(Task task) {
    _tasks.add(task);

    final Map storageMap = {}; // temporary map that gets added to storage

    storageMap['name'] = task.name;
    storageMap['description'] = task.description;
    storageMap['key'] = task.key;

    storageList[task.key] = storageMap; // adding temp map to storageList
    box.write('tasks', storageList); // adding map of maps to storage
  }

Then your restore function would look like this:

 void restoreTasks() {
    storageList = box.read('tasks'); // initializing list from storage

    storageList.forEach((key, value) { // value here is each individual map that was stored
      final task =
          Task(name: value['name'], description: value['description'], key: key);
      _tasks.add(task);
    });
  }

Then when you go to delete, you iterate through the list and find the matching key.

Related