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