@@ -514,8 +514,10 @@ class HotRunner extends ResidentRunner {
514
514
String reason,
515
515
bool benchmarkMode = false ,
516
516
}) async {
517
- globals.printTrace ('Refreshing active FlutterViews before restarting.' );
518
- await refreshViews ();
517
+ if (! _isPaused ()) {
518
+ globals.printTrace ('Refreshing active FlutterViews before restarting.' );
519
+ await refreshViews ();
520
+ }
519
521
520
522
final Stopwatch restartTimer = Stopwatch ()..start ();
521
523
// TODO(aam): Add generator reset logic once we switch to using incremental
@@ -540,36 +542,31 @@ class HotRunner extends ResidentRunner {
540
542
// Check if the isolate is paused and resume it.
541
543
final List <Future <void >> operations = < Future <void >> [];
542
544
for (final FlutterDevice device in flutterDevices) {
543
- final Set <String > uiIsolatesIds = < String > {};
545
+ final Set <Isolate > uiIsolates = < Isolate > {};
544
546
for (final FlutterView view in device.views) {
545
547
if (view.uiIsolate == null ) {
546
548
continue ;
547
549
}
548
- uiIsolatesIds .add (view.uiIsolate.id );
550
+ uiIsolates .add (view.uiIsolate);
549
551
// Reload the isolate.
550
- final Future <vm_service.Isolate > reloadIsolate = device.vmService
551
- .getIsolateOrNull (view.uiIsolate.id);
552
- operations.add (reloadIsolate.then ((vm_service.Isolate isolate) async {
553
- if ((isolate != null ) && isPauseEvent (isolate.pauseEvent.kind)) {
552
+ operations.add (view.uiIsolate.reload ().then ((ServiceObject _) {
553
+ final ServiceEvent pauseEvent = view.uiIsolate.pauseEvent;
554
+ if ((pauseEvent != null ) && pauseEvent.isPauseEvent) {
554
555
// Resume the isolate so that it can be killed by the embedder.
555
- await device.vmService.resume (view.uiIsolate.id);
556
+ return device.vmService.resume (view.uiIsolate.id);
556
557
}
558
+ return null ;
557
559
}));
558
560
}
559
-
560
561
// The engine handles killing and recreating isolates that it has spawned
561
562
// ("uiIsolates"). The isolates that were spawned from these uiIsolates
562
563
// will not be restared, and so they must be manually killed.
563
- final vm_service.VM vm = await device.vmService.getVM ();
564
- for (final vm_service.IsolateRef isolateRef in vm.isolates) {
565
- if (uiIsolatesIds.contains (isolateRef.id)) {
566
- continue ;
564
+ for (final Isolate isolate in device? .flutterDeprecatedVmService? .vm? .isolates ?? < Isolate > []) {
565
+ if (! uiIsolates.contains (isolate)) {
566
+ operations.add (isolate.invokeRpcRaw ('kill' , params: < String , dynamic > {
567
+ 'isolateId' : isolate.id,
568
+ }));
567
569
}
568
- operations.add (device.vmService.kill (isolateRef.id)
569
- .catchError ((dynamic error, StackTrace stackTrace) {
570
- // Do nothing on a SentinelException since it means the isolate
571
- // has already been killed.
572
- }, test: (dynamic error) => error is vm_service.SentinelException ));
573
570
}
574
571
}
575
572
await Future .wait (operations);
@@ -592,11 +589,13 @@ class HotRunner extends ResidentRunner {
592
589
} on vm_service.RPCError {
593
590
// Do nothing, we're already subcribed.
594
591
}
595
- isolateNotifications.add (
596
- device.vmService.onIsolateEvent.firstWhere ((vm_service.Event event) {
597
- return event.kind == vm_service.EventKind .kIsolateRunnable;
598
- }),
599
- );
592
+ for (final FlutterView view in device.views) {
593
+ isolateNotifications.add (
594
+ view.owner.vm.vmService.onIsolateEvent.firstWhere ((vm_service.Event event) {
595
+ return event.kind == vm_service.EventKind .kIsolateRunnable;
596
+ }),
597
+ );
598
+ }
600
599
}
601
600
await Future .wait (isolateNotifications);
602
601
}
@@ -819,9 +818,11 @@ class HotRunner extends ResidentRunner {
819
818
820
819
final Stopwatch reloadTimer = Stopwatch ()..start ();
821
820
822
- globals.printTrace ('Refreshing active FlutterViews before reloading.' );
823
- await refreshVM ();
824
- await refreshViews ();
821
+ if (! _isPaused ()) {
822
+ globals.printTrace ('Refreshing active FlutterViews before reloading.' );
823
+ await refreshVM ();
824
+ await refreshViews ();
825
+ }
825
826
826
827
final Stopwatch devFSTimer = Stopwatch ()..start ();
827
828
final UpdateFSReport updatedDevFS = await _updateDevFS ();
@@ -913,19 +914,27 @@ class HotRunner extends ResidentRunner {
913
914
// Record time it took for the VM to reload the sources.
914
915
_addBenchmarkData ('hotReloadVMReloadMilliseconds' , vmReloadTimer.elapsed.inMilliseconds);
915
916
final Stopwatch reassembleTimer = Stopwatch ()..start ();
916
-
917
- // Reload the isolate data.
918
- await Future .wait (< Future <void >> [
919
- for (final FlutterDevice device in flutterDevices)
920
- device.refreshViews ()
921
- ]);
917
+ // Reload the isolate.
918
+ final List <Future <void >> allDevices = < Future <void >> [];
919
+ for (final FlutterDevice device in flutterDevices) {
920
+ globals.printTrace ('Sending reload events to ${device .device .name }' );
921
+ final List <Future <ServiceObject >> futuresViews = < Future <ServiceObject >> [];
922
+ for (final FlutterView view in device.views) {
923
+ globals.printTrace ('Sending reload event to "${view .uiIsolate .name }"' );
924
+ futuresViews.add (view.uiIsolate.reload ());
925
+ }
926
+ allDevices.add (Future .wait (futuresViews).whenComplete (() {
927
+ return device.refreshViews ();
928
+ }));
929
+ }
930
+ await Future .wait (allDevices);
922
931
923
932
globals.printTrace ('Evicting dirty assets' );
924
933
await _evictDirtyAssets ();
925
934
926
935
// Check if any isolates are paused and reassemble those
927
936
// that aren't.
928
- final Map <FlutterView , vm_service. VmService > reassembleViews = < FlutterView , vm_service. VmService > {} ;
937
+ final List <FlutterView > reassembleViews = < FlutterView > [] ;
929
938
final List <Future <void >> reassembleFutures = < Future <void >> [];
930
939
String serviceEventKind;
931
940
int pausedIsolatesFound = 0 ;
@@ -934,20 +943,16 @@ class HotRunner extends ResidentRunner {
934
943
for (final FlutterView view in device.views) {
935
944
// Check if the isolate is paused, and if so, don't reassemble. Ignore the
936
945
// PostPauseEvent event - the client requesting the pause will resume the app.
937
- final vm_service.Isolate isolate = await device.vmService
938
- .getIsolateOrNull (view.uiIsolate.id);
939
- final vm_service.Event pauseEvent = isolate? .pauseEvent;
940
- if (pauseEvent != null
941
- && isPauseEvent (pauseEvent.kind)
942
- && pauseEvent.kind != vm_service.EventKind .kPausePostRequest) {
946
+ final ServiceEvent pauseEvent = view.uiIsolate.pauseEvent;
947
+ if (pauseEvent != null && pauseEvent.isPauseEvent && pauseEvent.kind != ServiceEvent .kPausePostRequest) {
943
948
pausedIsolatesFound += 1 ;
944
949
if (serviceEventKind == null ) {
945
950
serviceEventKind = pauseEvent.kind;
946
951
} else if (serviceEventKind != pauseEvent.kind) {
947
952
serviceEventKind = '' ; // many kinds
948
953
}
949
954
} else {
950
- reassembleViews[view] = device.vmService ;
955
+ reassembleViews. add (view) ;
951
956
reassembleFutures.add (device.vmService.flutterReassemble (
952
957
isolateId: view.uiIsolate.id,
953
958
).catchError ((dynamic error) {
@@ -969,7 +974,6 @@ class HotRunner extends ResidentRunner {
969
974
assert (reassembleViews.isNotEmpty);
970
975
971
976
globals.printTrace ('Reassembling application' );
972
-
973
977
final Future <void > reassembleFuture = Future .wait <void >(reassembleFutures);
974
978
await reassembleFuture.timeout (
975
979
const Duration (seconds: 2 ),
@@ -982,17 +986,14 @@ class HotRunner extends ResidentRunner {
982
986
globals.printTrace ('This is taking a long time; will now check for paused isolates.' );
983
987
int postReloadPausedIsolatesFound = 0 ;
984
988
String serviceEventKind;
985
- for (final FlutterView view in reassembleViews.keys) {
986
- final vm_service.Isolate isolate = await reassembleViews[view]
987
- .getIsolateOrNull (view.uiIsolate.id);
988
- if (isolate == null ) {
989
- continue ;
990
- }
991
- if (isolate.pauseEvent != null && isPauseEvent (isolate.pauseEvent.kind)) {
989
+ for (final FlutterView view in reassembleViews) {
990
+ await view.uiIsolate.reload ();
991
+ final ServiceEvent pauseEvent = view.uiIsolate.pauseEvent;
992
+ if (pauseEvent != null && pauseEvent.isPauseEvent) {
992
993
postReloadPausedIsolatesFound += 1 ;
993
994
if (serviceEventKind == null ) {
994
- serviceEventKind = isolate. pauseEvent.kind;
995
- } else if (serviceEventKind != isolate. pauseEvent.kind) {
995
+ serviceEventKind = pauseEvent.kind;
996
+ } else if (serviceEventKind != pauseEvent.kind) {
996
997
serviceEventKind = '' ; // many kinds
997
998
}
998
999
}
@@ -1068,33 +1069,32 @@ class HotRunner extends ResidentRunner {
1068
1069
}
1069
1070
assert (serviceEventKind != null );
1070
1071
switch (serviceEventKind) {
1071
- case vm_service.EventKind .kPauseStart:
1072
- message.write ('paused (probably due to --start-paused)' );
1073
- break ;
1074
- case vm_service.EventKind .kPauseExit:
1075
- message.write ('paused because ${ plural ? 'they have' : 'it has' } terminated' );
1076
- break ;
1077
- case vm_service.EventKind .kPauseBreakpoint:
1078
- message.write ('paused in the debugger on a breakpoint' );
1079
- break ;
1080
- case vm_service.EventKind .kPauseInterrupted:
1081
- message.write ('paused due in the debugger' );
1082
- break ;
1083
- case vm_service.EventKind .kPauseException:
1084
- message.write ('paused in the debugger after an exception was thrown' );
1085
- break ;
1086
- case vm_service.EventKind .kPausePostRequest:
1087
- message.write ('paused' );
1088
- break ;
1089
- case '' :
1090
- message.write ('paused for various reasons' );
1091
- break ;
1072
+ case ServiceEvent .kPauseStart: message.write ('paused (probably due to --start-paused)' ); break ;
1073
+ case ServiceEvent .kPauseExit: message.write ('paused because ${ plural ? 'they have' : 'it has' } terminated' ); break ;
1074
+ case ServiceEvent .kPauseBreakpoint: message.write ('paused in the debugger on a breakpoint' ); break ;
1075
+ case ServiceEvent .kPauseInterrupted: message.write ('paused due in the debugger' ); break ;
1076
+ case ServiceEvent .kPauseException: message.write ('paused in the debugger after an exception was thrown' ); break ;
1077
+ case ServiceEvent .kPausePostRequest: message.write ('paused' ); break ;
1078
+ case '' : message.write ('paused for various reasons' ); break ;
1092
1079
default :
1093
1080
message.write ('paused' );
1094
1081
}
1095
1082
return message.toString ();
1096
1083
}
1097
1084
1085
+ bool _isPaused () {
1086
+ for (final FlutterDevice device in flutterDevices) {
1087
+ for (final FlutterView view in device.views) {
1088
+ if (view.uiIsolate != null ) {
1089
+ final ServiceEvent pauseEvent = view.uiIsolate.pauseEvent;
1090
+ if (pauseEvent != null && pauseEvent.isPauseEvent) {
1091
+ return true ;
1092
+ }
1093
+ }
1094
+ }
1095
+ }
1096
+ return false ;
1097
+ }
1098
1098
1099
1099
@override
1100
1100
void printHelp ({ @required bool details }) {
@@ -1134,7 +1134,7 @@ class HotRunner extends ResidentRunner {
1134
1134
}
1135
1135
for (final String assetPath in device.devFS.assetPathsToEvict) {
1136
1136
futures.add (
1137
- device.vmService
1137
+ device.views.first.uiIsolate. vmService
1138
1138
.flutterEvictAsset (
1139
1139
assetPath,
1140
1140
isolateId: device.views.first.uiIsolate.id,
0 commit comments