Changing property of children don't trigger UI change on Flutter Getx

1.8k Views Asked by At

I'm trying to render a reactive widget, based on a object list.

I needed that when the children of this object, has his boolean property changes, the UI should be updated.

In this scenario, my controller has a list os Sections and each section has a list of Lessons.

To better understanding, i rewriter my code making a simple example, based on what i need. I already try using .map, .forEach, and others approaches, but the children property never trigger the UI update.

GetX<LessonController>(
  initState: (state) => controller.getLessonsByCourse(course.id),
  builder: (_) {
    return Expanded(
      child: ListView.separated(
        scrollDirection: Axis.vertical,
        itemCount: _.sectionList.length,
        itemBuilder: (BuildContext context, int index) {
          return ExpansionTile(
              title: Text(_.sectionList[index].title),
              children: <Widget>[
                for(var i = 0; i < _.sectionList[index].lessons.length; i++)
                  Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: 
                      Obx(() => 
                        GestureDetector(
                          child: Text((_.sectionList[index].lessons[i] as Lesson).isCompleted.toString()),
                          onTap: () {
                            (_.sectionList[index].lessons[i] as Lesson).isCompleted = !(_.sectionList[index].lessons[i]as Lesson).isCompleted;
                            print((_.sectionList[index].lessons[i]as Lesson).isCompleted.toString());
                          })
                      ),
                  )
              ]);
        },
        separatorBuilder: (context, ind) => Divider(
          height: 2,
          color: Colors.grey[300],
        ),
      ),
    );
  })

Solution:

The GetX container monitores changes on the list items, so when you change a property from one of this items, the list itself doesn't change. To solved that, i change the item property, and after that i overrited it on the list.

onTap: (value) {
    Section tappedSection = _.sectionList[index];
    tappedSection.lessons[lessonIndex].isCompleted = value;
    // This is the secret
    // Making GetX detect a change on the list and rebuild UI
    _.sectionList[index] = tappedSection;
}));
2

There are 2 best solutions below

0
On

As far as I could tell, an observable list in Flutter GetX is not concerned with internal changes to objects in itself.

To force the UI update, I had to return the updated object to the same position in the list, in order to pretend that there was a change in the objects in the main list.

Something like that:

Section tappedSection = _.sectionList[index];
tappedSection.lessons[i].isCompleted = value;
_.notifyLessonProgress(tappedSection.lessons[i].id, value);
_.sectionList[index] = tappedSection;
1
On

It looks like the problem is here: this._sectionList.value = value;

Try this instead: this._sectionList = value;