The Widget inside the Getx/Obx didn't rebuild

158 Views Asked by At

Hi guys i had Rxint (completed) that change its value from the function (completedTask) that is used for calculate the completed task from the local db and save it in the Rxint (completed) the problem is the widget did't rebuild when i change the value unless i use the host reload i tried so much without any soliotion ,plz help me this is the widget:

Obx(() {
              return CircularStepProgressIndicator(
                totalSteps: todoDb.data?.length??1,
                currentStep: todoDb.completed.value,
                selectedColor: Colors.yellow,
                unselectedColor: Colors.lightBlueAccent,
                padding: 0,
                width: 50,
                height: 50,
                child: const Icon(
                  Icons.download_done_outlined,
                  color: Colors.blueAccent,
                  size: 20,
                ),
              );
            }
    );

  }

and this is the used function:

class TodoDb{
  Rx<int> completed=0.obs;

  completedTask(bool isUpd) async {
    if(isUpd==false){
      await readData();
    }
    for (var e in data!) {
      if (e['isDone'] == 1) {
        completed.value = completed.value + 1;
      }
    }
    print(completed.value);
    return completed.value;
  }


2

There are 2 best solutions below

0
On

Ok I see is not your fault, it's a package issue, I was checking the code https://github.com/SandroMaglione/step-progress-indicator/blob/master/lib/src/circular_step_progress_indicator.dart#L527C3-L528C72 and it's not refreshing the custompainter because the condition is wrong.

If you want to force the widget refresh, you could use a different key and it will re-insert the widget into the widget tree.

Add this key property:

return CircularStepProgressIndicator(
           key: ValueKey(todoController.completed.value),
           ...
1
On

Use RxInt instead of Rx<int>

Consider using RxInt instead of Rx<int> for better performance.

Use GetxController class

Use a GetxController instead of a plain class. This provides the update method, which notifies listeners about the change.

So your code should look like this:

class TodoController extends GetxController {
  RxInt completed = 0.obs;

  completedTask(bool isUpd) async {
    if (isUpd == false) {
      await readData();
    }
    for (var e in data!) {
      if (e['isDone'] == 1) {
        completed.value = completed.value + 1;
      }
    }
    print(completed.value);
    return completed.value;
  }
}

and your widget something like this:

  Obx(() {
    return CircularStepProgressIndicator(
      totalSteps: todoController.data?.length ?? 1,
      currentStep: todoController.completed.value,
      selectedColor: Colors.yellow,
      unselectedColor: Colors.lightBlueAccent,
      padding: 0,
      width: 50,
      height: 50,
      child: const Icon(
        Icons.download_done_outlined,
        color: Colors.blueAccent,
        size: 20,
      ),
    );
  }
  );

you also need to initialize the TodoController at a suitable place:

final todoController = Get.put(TodoController());