2

我正在尝试基于对象列表呈现反应式小部件。

我需要当这个对象的子对象的布尔属性发生变化时,应该更新 UI。

在这种情况下,我的控制器有一个 os Sections 列表,每个部分都有一个 Lessons 列表。

为了更好地理解,我根据我的需要重写了我的代码,制作了一个简单的例子。我已经尝试使用 .map、.forEach 和其他方法,但是 children 属性永远不会触发 UI 更新。

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],
        ),
      ),
    );
  })

解决方案:

GetX 容器监视列表项的更改,因此当您更改其中一项的属性时,列表本身不会更改。为了解决这个问题,我更改了 item 属性,然后我在列表中覆盖了它。

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;
}));
4

2 回答 2

1

据我所知,Flutter GetX 中的可观察列表并不关心对象本身的内部变化。

为了强制 UI 更新,我不得不将更新后的对象返回到列表中的相同位置,以假装主列表中的对象发生了变化。

像这样的东西:

Section tappedSection = _.sectionList[index];
tappedSection.lessons[i].isCompleted = value;
_.notifyLessonProgress(tappedSection.lessons[i].id, value);
_.sectionList[index] = tappedSection;
于 2020-10-08T13:57:40.200 回答
0

看起来问题出在这里: this._sectionList.value = value;

试试这个: this._sectionList = value;

于 2020-10-07T17:59:54.953 回答