简体   繁体   中英

ValueListenableBuilder is not rebuilding the screen, when hotreloading, it is working

I'm trying to build a note app, all data and other things is working perfectly, cos the data is displaying to the screen when the code file is saving, its weird, first time facing this problem

in short, the valuelistanble is not listening when the data adding from app, but when just hot reloading the data is displaying

how can i fix this, here is the code

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    WidgetsBinding.instance!.addPostFrameCallback((_) async {
      final value = await NoteDB.instance.getAllNotes();
    });

           ____________________________________________
           ____________________________________________
           //code line for aligment 

            Expanded(
                child: ValueListenableBuilder(
              valueListenable: NoteDB.instance.noteListNotifier,
              builder: (context, List<NoteModel> newNotes, _) {
                return GridView.count(
                  childAspectRatio: 3 / 4,
                  crossAxisCount: 2,
                  mainAxisSpacing: 34,
                  crossAxisSpacing: 30,
                  padding: const EdgeInsets.all(20),
                  //generating list for all note
                  children: List.generate(
                    newNotes.length,
                    (index) {
                      //setting the notelist to a variable called [note]
                      final note = newNotes[index];
                      if (note.id == null) {
                        //if the note's id is null set to sizedbox
                        //the note id never be null
                        const SizedBox();
                      }
                      return NoteItem(
                        id: note.id!,
                        //the ?? is the statement (if null)
                        content: note.content ?? 'No Content',
                        title: note.title ?? 'No Title',
                      );
                    },
                  ),
                );
              },
            )),

here is the NoteDB.instance.getAllNotes(); function

       @override
  Future<List<NoteModel>> getAllNotes() async {
  

    final _result = await dio.get(url.baseUrl+url.getAllNotes);
    if (_result.data != null) {
      final  noteResponse = GetAllNotes.fromJson(_result.data);
      noteListNotifier.value.clear();
      noteListNotifier.value.addAll(noteResponse.data.reversed);
      noteListNotifier.notifyListeners();
      return noteResponse.data;
    } else {
      noteListNotifier.value.clear();
      return [];
    }

  }

and also there is a page to create note, and when create note button pressed there is only one function calling here is function

Future<void> saveNote() async {
    final title = titleController.text;
    final content = contentController.text;
    final _newNote = NoteModel.create(
      id: DateTime.now().millisecondsSinceEpoch.toString(),
      title: title,
      content: content,
    );
    final newNote = await NoteDB().createNote(_newNote);
    if (newNote != null) {
      print('Data Added to the DataBase Succesfully!');
      Navigator.of(scaffoldKey.currentContext!).pushAndRemoveUntil(
              MaterialPageRoute(
                  builder: (context) => HomePage()),
              (Route<dynamic> route) => false);
    } else {
      print('Error caught while data adding to the DataBase');
    }
  }

everything work fine, but while add the data the UI isn't refreshing even tho notifier is active

and if you need full code please have a look at this github link: https://github.com/Mishalhaneef/Note-app

Since this ValueNotifier has a type of List<NoteModel> , the value will not change when you add new items to the list or delete from it or clear all. The value here is a reference to the list which does not change.

You have to assign a new value to it, like:

noteListNotifier.value = List<NoteModel>[<add your current items here>];

You can manipulate your current list with List.from , removeWhere , add etc., and then re-assign the complete list.

Besides you don't need to call notifyListeners in case of a ValueNotifier , the framework handles it, see here .

Another approach would be to use a custom ChangeNotifierProvider where you can call notifyListeners when the contents of your list are changed.

Some further suggestions:

  1. In your homescreen.dart file, instead of NoteDB.instance.noteListNotifier.value[index] you can use newNotes[index] .

  2. In data.dart , within getAllNotes , you have to set a new value for noteListNotifier in order to get the changes propagated. Currently you are just modifying items in this list and that is not considered to be a change. Try this code:

  @override
  Future<List<NoteModel>> getAllNotes() async {
    //patching all data from local server using the url from [Post Man]
    final _result = await dio.get(url.baseUrl+url.getAllNotes);
    if (_result.data != null) {
      //if the result data is not null the rest operation will be operate
      //recived data's data decoding to json map
      final _resultAsJsonMap = jsonDecode(_result.data);
      //and that map converting to dart class and storing to another variable
      final getNoteResponse = GetAllNotes.fromJson(_resultAsJsonMap);
      noteListNotifier.value = getNoteResponse.data.reversed;
      //and returning the class
      return getNoteResponse.data;
    } else {
      noteListNotifier.value = <NoteModel>[];
      return [];
    }
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM