Skip to content

[SchedulerBinding] SchedulerBinding.instance.scheduleTask is jammed when Priority is idle #73766

@SixSheeppp

Description

@SixSheeppp

I found SchedulerBinding.instance.scheduleTask can be stucked in a specific scene.

Here is my example code

const tag = "ScheduleTest";

class ScheduleTestPage1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Center(
            child: Container(
              width: 50,
              height: 50,
              child: CircularProgressIndicator(),
            ),
          ),
          FlatButton(
              onPressed: () {
                Navigator.of(context).push(MaterialPageRoute(builder: (context) {
                  return ScheduleTestPage2();
                })).then((value) {
                  SchedulerBinding.instance.scheduleTask(() {
                    print("$tag>>>>>>scheduleTask1");
                  }, Priority.touch);

                  Future.delayed(Duration(seconds: 1), () {
                    SchedulerBinding.instance.scheduleTask(() {
                      print("$tag>>>>>>scheduleTask2");
                    }, Priority.touch);
                  });
                });
              },
              child: Text("click me "))
        ],
      ),
    );
  }
}

class ScheduleTestPage2 extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _ScheduleTest2State();
  }
}

class _ScheduleTest2State extends State<ScheduleTestPage2> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Container(
          width: 100,
          height: 50,
          child: FlatButton(
            onPressed: () {
              Navigator.of(context).pop();
            },
            child: Text("Back"),
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    SchedulerBinding.instance.scheduleTask(() {
      print("$tag>>>>>> call ScheduleTestPage2 dispose");
      // do something such as Exception .    throw Exception("Exception Test");
    }, Priority.idle);
  }
}

The console just print 1 log.
image

After debug the SchedulerBinding, I found the task was not been executed because of these code.

bool defaultSchedulingStrategy({ required int priority, required SchedulerBinding scheduler }) {
if (scheduler.transientCallbackCount > 0)
return priority >= Priority.animation.value;
return true;
}

The transientCallbackCount will be increased by Ticker in SingleTickerProviderStateMixin.didChangeDependencies

set muted(bool value) {
if (value == muted)
return;
_muted = value;
if (value) {
unscheduleTick();
} else if (shouldScheduleTick) {
scheduleTick();
}
}

I draw a timeline might explain the issue.
image

Because of _taskQueue.isEmpty is not true, so the remain task will not have chance to be executed :(

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority issues at the top of the work lista: animationAnimation APIscustomer: money (g3)found in release: 3.19Found to occur in 3.19found in release: 3.21Found to occur in 3.21frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionteam-frameworkOwned by Framework teamtriaged-frameworkTriaged by Framework team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions