flutterlistdartlistviewapplication-restart

After restarting flutter app, the added elements to the list are removed and from UI too


The Problem is that the List elements that the user enters in Textfields are rendered correctly. After App restart, the elements are removed from the List and from UI too. Here is the code: I created a model class with variables

class CardData {
CardData(this.name, this.university, this.department, this.rollNumber,
  this.emailId);
final String name;
final String university;
final String department;
final String rollNumber;
final String emailId;
}

Here is the form I used to get Data from user

import 'package:flutter/material.dart';
import 'package:student_card/models/card_data.dart';

class MyForm extends StatefulWidget {
  const MyForm({super.key, required this.onAddNewData});
  final void Function(CardData newData) onAddNewData;

  @override
  State<MyForm> createState() => _MyFormState();
}

class _MyFormState extends State<MyForm> {
  final nameController = TextEditingController();
  final universityController = TextEditingController();
  final departmentController = TextEditingController();
  final rollController = TextEditingController();
  final emailIdController = TextEditingController();

  @override
  void dispose() {
    nameController.dispose();
    universityController.dispose();
    departmentController.dispose();
    rollController.dispose();
    emailIdController.dispose();
    super.dispose();
  }

  OutlineInputBorder myfocusborder() {
    return const OutlineInputBorder(
    borderRadius: BorderRadius.all(Radius.circular(20)),
    borderSide: BorderSide(
      color: Colors.greenAccent,
      width: 3,
    ));
  }

  OutlineInputBorder myinputborder() {
    //return type is OutlineInputBorder
    return const OutlineInputBorder(
    //Outline border type for TextFeild
    borderRadius: BorderRadius.all(Radius.circular(20)),
    borderSide: BorderSide(
      color: Colors.redAccent,
      width: 3,
    ));
  }

  showUserData() {
    widget.onAddNewData(CardData(
    nameController.text,
    universityController.text,
    departmentController.text,
    rollController.text,
    emailIdController.text));
  }

  @override
  Widget build(BuildContext context) {

    return Column(
      children: [
        const SizedBox(
      height: 30,
    ),
    TextField(
      // cursorColor: Theme.of(context).colorScheme.onPrimary,
      controller: nameController,
      decoration: InputDecoration(
          label: const Text('Your Name'),
          hintText: 'Name',
          border: myinputborder(),
          focusedBorder: myfocusborder(),
          enabledBorder: myinputborder()),
    ),
    const SizedBox(
      height: 20,
    ),
    TextField(
      controller: universityController,
      decoration: InputDecoration(
          label: const Text('University Name'),
          hintText: 'University',
          border: myinputborder(),
          focusedBorder: myfocusborder(),
          enabledBorder: myinputborder()),
    ),
    const SizedBox(
      height: 20,
    ),
    TextField(
      controller: departmentController,
      decoration: InputDecoration(
          label: const Text('Your Department'),
          hintText: 'Department',
          border: myinputborder(),
          focusedBorder: myfocusborder(),
          enabledBorder: myinputborder()),
    ),
    const SizedBox(
      height: 20,
    ),
    TextField(
      controller: rollController,
      decoration: InputDecoration(
          label: const Text('Your Registration Id.'),
          hintText: 'Roll Numver',
          border: myinputborder(),
          focusedBorder: myfocusborder(),
          enabledBorder: myinputborder()),
    ),
    const SizedBox(
      height: 20,
    ),
    TextField(
      controller: emailIdController,
      decoration: InputDecoration(
          label: const Text('Your Email Id.'),
          hintText: 'Email',
          border: myinputborder(),
          focusedBorder: myfocusborder(),
          enabledBorder: myinputborder()),
    ),
    const SizedBox(
      height: 20,
    ),
    ElevatedButton(
        onPressed: () {
          showUserData();
        },
        child: const Text('Submit'))
      ],
    );
  }
}

List with dummy data and adding elements to it

import 'package:flutter/material.dart';
import 'package:student_card/Widgets/data_list.dart';
import 'package:student_card/models/card_data.dart';
import 'package:student_card/Widgets/form.dart';

class StudentCard extends StatefulWidget {
  const StudentCard({super.key});

  @override
  State<StudentCard> createState() {
    return _StudentCardState();
  }
}

class _StudentCardState extends State<StudentCard> {

  List<CardData> listData = [
    CardData('Moiz', 'UMT', 'Software', 'FA21-BEE-106', 'imoiz@gmail.com'),
  ];

  void addNewData(CardData newData) {
    setState(() {
      listData.add(newData);
    });
  }

  showFormSheet(BuildContext context) {
    showModalBottomSheet(
    isScrollControlled: true,
    context: context,
    builder: (context) {
      return Container(
        padding: const EdgeInsets.symmetric(
          horizontal: 20,
          vertical: 15,
        ),
        child: Column(
          children: [
            MyForm(
              onAddNewData: addNewData,
            )
          ],
        ),
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
    title: const Text('Student Card Maker'),
    backgroundColor: const Color(0xFFC539B4),
    actions: [
      IconButton(
          onPressed: () {
            showFormSheet(context);
          },
          icon: const Icon(Icons.add))
    ],
  ),
  body: Container(
    padding: const EdgeInsets.all(10),
    child: Column(
      children: [
        const Text('The data below'),
        const SizedBox(
          height: 10,
        ),
        Expanded(
          child: DataList(data: listData),
        )
      ],
    ),
  ),
    );
  }
} 

Rensdering it with ListView.Builder

import 'package:flutter/material.dart';
import 'package:student_card/models/card_data.dart';

class CardItem extends StatelessWidget {
  const CardItem({super.key, required this.studentData});
  final CardData studentData;
  @override
  Widget build(BuildContext context) {
    // Full screen width and height
    double Width = MediaQuery.of(context).size.width;
    double height = MediaQuery.of(context).size.height;

// Height (without SafeArea)
    var padding = MediaQuery.of(context).viewPadding;
    double height1 = height - padding.top - padding.bottom;
double realHeight = 0.75 * height1;
double realWidth = 0.90 * Width;

// Height (without status bar)
// double height2 = height - padding.top;

return Container(
  height: realHeight,
  width: realWidth,
  padding: const EdgeInsets.all(5),
  child: Card(
    child: Column(
      children: [
        Text(studentData.name),
        Text(studentData.university),
        Text(studentData.department),
        Text(studentData.rollNumber),
        Text(studentData.emailId),
      ],
    ),
     ),
  ),
);
  }
}

Solution

  • Okay, see when the app restarts it start the execution from the main with releasing all your previous memory usage, so you want to preserve the data entered by the user so that it is not lost when the app is restarted. So there are few different ways to achieve it: shared_preferences, sqflite and hive.

    So, with Shared Preferences, you can save simple stuff like settings or small user data. It's good when you don't need fancy queries. Here it's not applicable with your case (still if you want to use it you can covert your card model to json and save it. but i don't recommend it.)

    Now, SQLite using the sqflite package is great for structured and larger datasets. You can do all sorts of database stuff with it, like adding, reading, updating, and deleting data. It's best for your data, you just make a table for card and add new entries in table and retrieve at app restart.

    Lastly, there's Hive. It's nice for lightweight data storage, like lists or maps. It's quick and easy to use, especially when you don't want to deal with complex databases. It's like Map (key value pair),