Move async from member access to construction (#20035)

diff --git a/packages/flutter_tools/lib/src/android/android_device.dart b/packages/flutter_tools/lib/src/android/android_device.dart
index 1a3c554..f6d8cfd 100644
--- a/packages/flutter_tools/lib/src/android/android_device.dart
+++ b/packages/flutter_tools/lib/src/android/android_device.dart
@@ -375,14 +375,15 @@
 
     if (!prebuiltApplication) {
       printTrace('Building APK');
+      final FlutterProject project = await FlutterProject.current();
       await buildApk(
-          project: new FlutterProject(fs.currentDirectory),
+          project: project,
           target: mainPath,
           buildInfo: buildInfo,
       );
       // Package has been built, so we can get the updated application ID and
       // activity name from the .apk.
-      package = await AndroidApk.fromAndroidProject(new FlutterProject(fs.currentDirectory).android);
+      package = await AndroidApk.fromAndroidProject(project.android);
     }
 
     printTrace("Stopping app '${package.name}' on $name.");
diff --git a/packages/flutter_tools/lib/src/android/gradle.dart b/packages/flutter_tools/lib/src/android/gradle.dart
index 4fa661b..8842503 100644
--- a/packages/flutter_tools/lib/src/android/gradle.dart
+++ b/packages/flutter_tools/lib/src/android/gradle.dart
@@ -90,7 +90,7 @@
 // Note: Dependencies are resolved and possibly downloaded as a side-effect
 // of calculating the app properties using Gradle. This may take minutes.
 Future<GradleProject> _readGradleProject() async {
-  final FlutterProject flutterProject =  new FlutterProject(fs.currentDirectory);
+  final FlutterProject flutterProject = await FlutterProject.current();
   final String gradle = await _ensureGradle(flutterProject);
   await updateLocalProperties(project: flutterProject);
   final Status status = logger.startProgress('Resolving dependencies...', expectSlowOperation: true);
@@ -214,7 +214,7 @@
     throwToolExit('Unable to locate Android SDK. Please run `flutter doctor` for more details.');
   }
 
-  final File localProperties = await project.androidLocalPropertiesFile;
+  final File localProperties = project.androidLocalPropertiesFile;
   bool changed = false;
 
   SettingsFile settings;
@@ -232,7 +232,7 @@
     }
   }
 
-  final FlutterManifest manifest = await project.manifest;
+  final FlutterManifest manifest = project.manifest;
 
   if (androidSdk != null)
     changeIfNecessary('sdk.dir', escapePath(androidSdk.directory));
diff --git a/packages/flutter_tools/lib/src/application_package.dart b/packages/flutter_tools/lib/src/application_package.dart
index b1dbdaa..27e99bf 100644
--- a/packages/flutter_tools/lib/src/application_package.dart
+++ b/packages/flutter_tools/lib/src/application_package.dart
@@ -314,7 +314,7 @@
     case TargetPlatform.android_x64:
     case TargetPlatform.android_x86:
       return applicationBinary == null
-          ? await AndroidApk.fromAndroidProject(new FlutterProject(fs.currentDirectory).android)
+          ? await AndroidApk.fromAndroidProject((await FlutterProject.current()).android)
           : new AndroidApk.fromApk(applicationBinary);
     case TargetPlatform.ios:
       return applicationBinary == null
@@ -344,7 +344,7 @@
       case TargetPlatform.android_arm64:
       case TargetPlatform.android_x64:
       case TargetPlatform.android_x86:
-        android ??= await AndroidApk.fromAndroidProject(new FlutterProject(fs.currentDirectory).android);
+        android ??= await AndroidApk.fromAndroidProject((await FlutterProject.current()).android);
         return android;
       case TargetPlatform.ios:
         iOS ??= new IOSApp.fromCurrentDirectory();
diff --git a/packages/flutter_tools/lib/src/commands/build_apk.dart b/packages/flutter_tools/lib/src/commands/build_apk.dart
index 3dda93a..229b41b 100644
--- a/packages/flutter_tools/lib/src/commands/build_apk.dart
+++ b/packages/flutter_tools/lib/src/commands/build_apk.dart
@@ -5,7 +5,6 @@
 import 'dart:async';
 
 import '../android/apk.dart';
-import '../base/file_system.dart';
 import '../project.dart';
 import 'build.dart';
 
@@ -46,6 +45,10 @@
   @override
   Future<Null> runCommand() async {
     await super.runCommand();
-    await buildApk(project: new FlutterProject(fs.currentDirectory),target: targetFile, buildInfo: getBuildInfo());
+    await buildApk(
+      project: await FlutterProject.current(),
+      target: targetFile,
+      buildInfo: getBuildInfo(),
+    );
   }
 }
diff --git a/packages/flutter_tools/lib/src/commands/create.dart b/packages/flutter_tools/lib/src/commands/create.dart
index 7413905..b5f6cca 100644
--- a/packages/flutter_tools/lib/src/commands/create.dart
+++ b/packages/flutter_tools/lib/src/commands/create.dart
@@ -135,7 +135,8 @@
       dirPath = fs.path.dirname(dirPath);
     String organization = argResults['org'];
     if (!argResults.wasParsed('org')) {
-      final Set<String> existingOrganizations = await new FlutterProject(projectDir).organizationNames();
+      final FlutterProject project = await FlutterProject.fromDirectory(projectDir);
+      final Set<String> existingOrganizations = await project.organizationNames();
       if (existingOrganizations.length == 1) {
         organization = existingOrganizations.first;
       } else if (1 < existingOrganizations.length) {
@@ -167,20 +168,20 @@
     );
 
     printStatus('Creating project ${fs.path.relative(dirPath)}...');
+    final Directory directory = fs.directory(dirPath);
     int generatedFileCount = 0;
-    final FlutterProject project = new FlutterProject.fromPath(dirPath);
     switch (template) {
       case 'app':
-        generatedFileCount += await _generateApp(project, templateContext);
+        generatedFileCount += await _generateApp(directory, templateContext);
         break;
       case 'module':
-        generatedFileCount += await _generateModule(project, templateContext);
+        generatedFileCount += await _generateModule(directory, templateContext);
         break;
       case 'package':
-        generatedFileCount += await _generatePackage(project, templateContext);
+        generatedFileCount += await _generatePackage(directory, templateContext);
         break;
       case 'plugin':
-        generatedFileCount += await _generatePlugin(project, templateContext);
+        generatedFileCount += await _generatePlugin(directory, templateContext);
         break;
     }
     printStatus('Wrote $generatedFileCount files.');
@@ -193,6 +194,7 @@
       printStatus('Your module code is in lib/main.dart in the $relativePath directory.');
     } else {
       // Run doctor; tell the user the next steps.
+      final FlutterProject project = await FlutterProject.fromPath(dirPath);
       final FlutterProject app = project.hasExampleApp ? project.example : project;
       final String relativeAppPath = fs.path.relative(app.directory.path);
       final String relativePluginPath = fs.path.relative(dirPath);
@@ -233,57 +235,57 @@
     }
   }
 
-  Future<int> _generateModule(FlutterProject project, Map<String, dynamic> templateContext) async {
+  Future<int> _generateModule(Directory directory, Map<String, dynamic> templateContext) async {
     int generatedCount = 0;
     final String description = argResults.wasParsed('description')
         ? argResults['description']
         : 'A new flutter module project.';
     templateContext['description'] = description;
-    generatedCount += _renderTemplate(fs.path.join('module', 'common'), project.directory, templateContext);
+    generatedCount += _renderTemplate(fs.path.join('module', 'common'), directory, templateContext);
     if (argResults['pub']) {
       await pubGet(
         context: PubContext.create,
-        directory: project.directory.path,
+        directory: directory.path,
         offline: argResults['offline'],
       );
+      final FlutterProject project = await FlutterProject.fromDirectory(directory);
       await project.ensureReadyForPlatformSpecificTooling();
     }
     return generatedCount;
   }
 
-  Future<int> _generatePackage(FlutterProject project, Map<String, dynamic> templateContext) async {
+  Future<int> _generatePackage(Directory directory, Map<String, dynamic> templateContext) async {
     int generatedCount = 0;
     final String description = argResults.wasParsed('description')
        ? argResults['description']
        : 'A new flutter package project.';
     templateContext['description'] = description;
-    generatedCount += _renderTemplate('package', project.directory, templateContext);
-
+    generatedCount += _renderTemplate('package', directory, templateContext);
     if (argResults['pub']) {
       await pubGet(
         context: PubContext.createPackage,
-        directory: project.directory.path,
+        directory: directory.path,
         offline: argResults['offline'],
       );
     }
     return generatedCount;
   }
 
-  Future<int> _generatePlugin(FlutterProject project, Map<String, dynamic> templateContext) async {
+  Future<int> _generatePlugin(Directory directory, Map<String, dynamic> templateContext) async {
     int generatedCount = 0;
     final String description = argResults.wasParsed('description')
         ? argResults['description']
         : 'A new flutter plugin project.';
     templateContext['description'] = description;
-    generatedCount += _renderTemplate('plugin', project.directory, templateContext);
-
+    generatedCount += _renderTemplate('plugin', directory, templateContext);
     if (argResults['pub']) {
       await pubGet(
         context: PubContext.createPlugin,
-        directory: project.directory.path,
+        directory: directory.path,
         offline: argResults['offline'],
       );
     }
+    final FlutterProject project = await FlutterProject.fromDirectory(directory);
     if (android_sdk.androidSdk != null)
       await gradle.updateLocalProperties(project: project);
 
@@ -298,22 +300,23 @@
     templateContext['pluginProjectName'] = projectName;
     templateContext['androidPluginIdentifier'] = androidPluginIdentifier;
 
-    generatedCount += await _generateApp(project.example, templateContext);
+    generatedCount += await _generateApp(project.example.directory, templateContext);
     return generatedCount;
   }
 
-  Future<int> _generateApp(FlutterProject project, Map<String, dynamic> templateContext) async {
+  Future<int> _generateApp(Directory directory, Map<String, dynamic> templateContext) async {
     int generatedCount = 0;
-    generatedCount += _renderTemplate('create', project.directory, templateContext);
+    generatedCount += _renderTemplate('create', directory, templateContext);
+    final FlutterProject project = await FlutterProject.fromDirectory(directory);
     generatedCount += _injectGradleWrapper(project);
 
     if (argResults['with-driver-test']) {
-      final Directory testDirectory = project.directory.childDirectory('test_driver');
+      final Directory testDirectory = directory.childDirectory('test_driver');
       generatedCount += _renderTemplate('driver', testDirectory, templateContext);
     }
 
     if (argResults['pub']) {
-      await pubGet(context: PubContext.create, directory: project.directory.path, offline: argResults['offline']);
+      await pubGet(context: PubContext.create, directory: directory.path, offline: argResults['offline']);
       await project.ensureReadyForPlatformSpecificTooling();
     }
 
diff --git a/packages/flutter_tools/lib/src/commands/inject_plugins.dart b/packages/flutter_tools/lib/src/commands/inject_plugins.dart
index 6a1bb94..21aa60a 100644
--- a/packages/flutter_tools/lib/src/commands/inject_plugins.dart
+++ b/packages/flutter_tools/lib/src/commands/inject_plugins.dart
@@ -4,7 +4,6 @@
 
 import 'dart:async';
 
-import '../base/file_system.dart';
 import '../globals.dart';
 import '../plugins.dart';
 import '../project.dart';
@@ -26,7 +25,7 @@
 
   @override
   Future<Null> runCommand() async {
-    final FlutterProject project = new FlutterProject(fs.currentDirectory);
+    final FlutterProject project = await FlutterProject.current();
     await injectPlugins(project);
     final bool result = hasPlugins(project);
     if (result) {
diff --git a/packages/flutter_tools/lib/src/commands/packages.dart b/packages/flutter_tools/lib/src/commands/packages.dart
index ff71446..b78e25b 100644
--- a/packages/flutter_tools/lib/src/commands/packages.dart
+++ b/packages/flutter_tools/lib/src/commands/packages.dart
@@ -80,7 +80,7 @@
     }
 
     await _runPubGet(target);
-    final FlutterProject rootProject = new FlutterProject.fromPath(target);
+    final FlutterProject rootProject = await FlutterProject.fromPath(target);
     await rootProject.ensureReadyForPlatformSpecificTooling();
 
     // Get/upgrade packages in example app as well
diff --git a/packages/flutter_tools/lib/src/flutter_manifest.dart b/packages/flutter_tools/lib/src/flutter_manifest.dart
index 8d848b1..14c3ae9 100644
--- a/packages/flutter_tools/lib/src/flutter_manifest.dart
+++ b/packages/flutter_tools/lib/src/flutter_manifest.dart
@@ -20,6 +20,14 @@
 class FlutterManifest {
   FlutterManifest._();
 
+  /// Returns an empty manifest.
+  static FlutterManifest empty() {
+    final FlutterManifest manifest = new FlutterManifest._();
+    manifest._descriptor = <String, dynamic>{};
+    manifest._flutterDescriptor = <String, dynamic>{};
+    return manifest;
+  }
+
   /// Returns null on invalid manifest. Returns empty manifest on missing file.
   static Future<FlutterManifest> createFromPath(String path) async {
     if (path == null || !fs.isFileSync(path))
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart
index 2105872..e8890f1 100644
--- a/packages/flutter_tools/lib/src/ios/mac.dart
+++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -233,7 +233,7 @@
   final Directory appDirectory = fs.directory(app.appDirectory);
   await _addServicesToBundle(appDirectory);
 
-  final FlutterProject project = new FlutterProject(fs.currentDirectory);
+  final FlutterProject project = await FlutterProject.current();
   await updateGeneratedXcodeProperties(
     project: project,
     targetOverride: targetOverride,
diff --git a/packages/flutter_tools/lib/src/ios/xcodeproj.dart b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
index 4f7f6b5..3429810 100644
--- a/packages/flutter_tools/lib/src/ios/xcodeproj.dart
+++ b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
@@ -32,9 +32,9 @@
 /// if project is an iOS project and such files are out of date or do not
 /// already exist.
 Future<void> generateXcodeProperties({FlutterProject project}) async {
-  if ((await project.manifest).isModule ||
+  if (project.manifest.isModule ||
       project.ios.directory.existsSync()) {
-    if (!Cache.instance.fileOlderThanToolsStamp(await project.generatedXcodePropertiesFile)) {
+    if (!Cache.instance.fileOlderThanToolsStamp(project.generatedXcodePropertiesFile)) {
       return;
     }
 
@@ -79,7 +79,7 @@
 
   localsBuffer.writeln('SYMROOT=\${SOURCE_ROOT}/../${getIosBuildDirectory()}');
 
-  final FlutterManifest manifest = await project.manifest;
+  final FlutterManifest manifest = project.manifest;
   if (!manifest.isModule) {
     // For module projects we do not want to write the FLUTTER_FRAMEWORK_DIR
     // explicitly. Rather we rely on the xcode backend script and the Podfile
@@ -119,7 +119,7 @@
     localsBuffer.writeln('TRACK_WIDGET_CREATION=true');
   }
 
-  final File generatedXcodePropertiesFile = await project.generatedXcodePropertiesFile;
+  final File generatedXcodePropertiesFile = project.generatedXcodePropertiesFile;
   generatedXcodePropertiesFile.createSync(recursive: true);
   generatedXcodePropertiesFile.writeAsStringSync(localsBuffer.toString());
 }
diff --git a/packages/flutter_tools/lib/src/plugins.dart b/packages/flutter_tools/lib/src/plugins.dart
index 484d897..93590d2 100644
--- a/packages/flutter_tools/lib/src/plugins.dart
+++ b/packages/flutter_tools/lib/src/plugins.dart
@@ -158,7 +158,7 @@
   };
 
   final String javaSourcePath = fs.path.join(
-    (await project.androidPluginRegistrantHost).path,
+    project.androidPluginRegistrantHost.path,
     'src',
     'main',
     'java',
@@ -247,8 +247,8 @@
     'plugins': iosPlugins,
   };
 
-  final String registryDirectory = (await project.iosPluginRegistrantHost).path;
-  if ((await project.manifest).isModule) {
+  final String registryDirectory = project.iosPluginRegistrantHost.path;
+  if (project.manifest.isModule) {
     final String registryClassesDirectory = fs.path.join(registryDirectory, 'Classes');
     _renderTemplateToFile(
       _iosPluginRegistrantPodspecTemplate,
diff --git a/packages/flutter_tools/lib/src/project.dart b/packages/flutter_tools/lib/src/project.dart
index bda7ede..ec0e109 100644
--- a/packages/flutter_tools/lib/src/project.dart
+++ b/packages/flutter_tools/lib/src/project.dart
@@ -15,20 +15,39 @@
 import 'template.dart';
 
 /// Represents the contents of a Flutter project at the specified [directory].
+///
+/// Instances should be treated as immutable snapshots, to be replaced by new
+/// instances on changes to `pubspec.yaml` files.
 class FlutterProject {
+  FlutterProject._(this.directory, this.manifest, this._exampleManifest);
 
-  FlutterProject(this.directory);
-  FlutterProject.fromPath(String projectPath) : directory = fs.directory(projectPath);
+  /// Returns a future that completes with a FlutterProject view of the given directory.
+  static Future<FlutterProject> fromDirectory(Directory directory) async {
+    final FlutterManifest manifest = await FlutterManifest.createFromPath(
+      directory.childFile(bundle.defaultManifestPath).path,
+    );
+    final Directory exampleDirectory = directory.childDirectory('example');
+    final FlutterManifest exampleManifest = await FlutterManifest.createFromPath(
+      exampleDirectory.childFile(bundle.defaultManifestPath).path,
+    );
+    return new FlutterProject._(directory, manifest, exampleManifest);
+  }
+
+  /// Returns a future that completes with a FlutterProject view of the current directory.
+  static Future<FlutterProject> current() => fromDirectory(fs.currentDirectory);
+
+  /// Returns a future that completes with a FlutterProject view of the given directory.
+  static Future<FlutterProject> fromPath(String path) => fromDirectory(fs.directory(path));
 
   /// The location of this project.
   final Directory directory;
 
-  Future<FlutterManifest> get manifest {
-    return _manifest ??= FlutterManifest.createFromPath(
-      directory.childFile(bundle.defaultManifestPath).path,
-    );
-  }
-  Future<FlutterManifest> _manifest;
+  /// The manifest of this project, or null, if `pubspec.yaml` is invalid.
+  final FlutterManifest manifest;
+
+  /// The manifest of the example sub-project of this project, or null, if
+  /// `example/pubspec.yaml` is invalid.
+  final FlutterManifest _exampleManifest;
 
   /// Asynchronously returns the organization names found in this project as
   /// part of iOS product bundle identifier, Android application ID, or
@@ -41,10 +60,9 @@
       example.android.applicationId(),
       example.ios.productBundleIdentifier(),
     ]);
-    return new Set<String>.from(
-      candidates.map(_organizationNameFromPackageName)
-                .where((String name) => name != null)
-    );
+    return new Set<String>.from(candidates
+        .map(_organizationNameFromPackageName)
+        .where((String name) => name != null));
   }
 
   String _organizationNameFromPackageName(String packageName) {
@@ -66,75 +84,52 @@
   /// The generated IosModule sub project of this module project.
   IosModuleProject get iosModule => new IosModuleProject(directory.childDirectory('.ios'));
 
-  Future<File> get androidLocalPropertiesFile {
-    return _androidLocalPropertiesFile ??= manifest.then<File>((FlutterManifest manifest) {
-      return directory.childDirectory(manifest.isModule ? '.android' : 'android')
-          .childFile('local.properties');
-    });
+  File get androidLocalPropertiesFile {
+    return directory
+        .childDirectory(manifest.isModule ? '.android' : 'android')
+        .childFile('local.properties');
   }
-  Future<File> _androidLocalPropertiesFile;
 
-  Future<File> get generatedXcodePropertiesFile {
-    return _generatedXcodeProperties ??= manifest.then<File>((FlutterManifest manifest) {
-      return directory.childDirectory(manifest.isModule ? '.ios' : 'ios')
-          .childDirectory('Flutter')
-          .childFile('Generated.xcconfig');
-    });
+  File get generatedXcodePropertiesFile {
+    return directory
+        .childDirectory(manifest.isModule ? '.ios' : 'ios')
+        .childDirectory('Flutter')
+        .childFile('Generated.xcconfig');
   }
-  Future<File> _generatedXcodeProperties;
 
-  File get flutterPluginsFile {
-    return _flutterPluginsFile ??= directory.childFile('.flutter-plugins');
+  File get flutterPluginsFile => directory.childFile('.flutter-plugins');
+
+  Directory get androidPluginRegistrantHost {
+    return manifest.isModule
+        ? directory.childDirectory('.android').childDirectory('Flutter')
+        : directory.childDirectory('android').childDirectory('app');
   }
-  File _flutterPluginsFile;
 
-  Future<Directory> get androidPluginRegistrantHost async {
-    return _androidPluginRegistrantHost ??= manifest.then((FlutterManifest manifest) {
-      if (manifest.isModule) {
-        return directory.childDirectory('.android').childDirectory('Flutter');
-      } else {
-        return directory.childDirectory('android').childDirectory('app');
-      }
-    });
+  Directory get iosPluginRegistrantHost {
+    // In a module create the GeneratedPluginRegistrant as a pod to be included
+    // from a hosting app.
+    // For a non-module create the GeneratedPluginRegistrant as source files
+    // directly in the iOS project.
+    return manifest.isModule
+        ? directory.childDirectory('.ios').childDirectory('Flutter').childDirectory('FlutterPluginRegistrant')
+        : directory.childDirectory('ios').childDirectory('Runner');
   }
-  Future<Directory> _androidPluginRegistrantHost;
 
-  Future<Directory> get iosPluginRegistrantHost async {
-    return _iosPluginRegistrantHost ??= manifest.then((FlutterManifest manifest) {
-      if (manifest.isModule) {
-        // In a module create the GeneratedPluginRegistrant as a pod to be included
-        // from a hosting app.
-        return directory
-            .childDirectory('.ios')
-            .childDirectory('Flutter')
-            .childDirectory('FlutterPluginRegistrant');
-      } else {
-        // For a non-module create the GeneratedPluginRegistrant as source files
-        // directly in the iOS project.
-        return directory.childDirectory('ios').childDirectory('Runner');
-      }
-    });
-  }
-  Future<Directory> _iosPluginRegistrantHost;
+  /// The example sub-project of this project.
+  FlutterProject get example => new FlutterProject._(_exampleDirectory, _exampleManifest, FlutterManifest.empty());
 
-  /// Returns true if this project has an example application
+  /// True, if this project has an example application
   bool get hasExampleApp => _exampleDirectory.childFile('pubspec.yaml').existsSync();
 
-  /// The example sub project of this (package or plugin) project.
-  FlutterProject get example => new FlutterProject(_exampleDirectory);
-
   /// The directory that will contain the example if an example exists.
   Directory get _exampleDirectory => directory.childDirectory('example');
 
   /// Generates project files necessary to make Gradle builds work on Android
   /// and CocoaPods+Xcode work on iOS, for app and module projects only.
-  ///
-  /// Returns the number of files written.
   Future<void> ensureReadyForPlatformSpecificTooling() async {
     if (!directory.existsSync() || hasExampleApp) {
-      return 0;
+      return;
     }
-    final FlutterManifest manifest = await this.manifest;
     if (manifest.isModule) {
       await androidModule.ensureReadyForPlatformSpecificTooling(this);
       await iosModule.ensureReadyForPlatformSpecificTooling();
@@ -152,9 +147,7 @@
   final Directory directory;
 
   /// The xcode config file for [mode].
-  File xcodeConfigFor(String mode) {
-    return directory.childDirectory('Flutter').childFile('$mode.xcconfig');
-  }
+  File xcodeConfigFor(String mode) => directory.childDirectory('Flutter').childFile('$mode.xcconfig');
 
   /// The 'Podfile'.
   File get podfile => directory.childFile('Podfile');
@@ -198,23 +191,16 @@
   AndroidProject(this.directory);
 
   File get gradleManifestFile {
-    return _gradleManifestFile ??= isUsingGradle()
+    return isUsingGradle()
         ? fs.file(fs.path.join(directory.path, 'app', 'src', 'main', 'AndroidManifest.xml'))
         : directory.childFile('AndroidManifest.xml');
   }
-  File _gradleManifestFile;
 
-
-  File get gradleAppOutV1File {
-    return _gradleAppOutV1File ??= gradleAppOutV1Directory.childFile('app-debug.apk');
-  }
-  File _gradleAppOutV1File;
+  File get gradleAppOutV1File => gradleAppOutV1Directory.childFile('app-debug.apk');
 
   Directory get gradleAppOutV1Directory {
-    return _gradleAppOutV1Directory ??= fs.directory(fs.path.join(directory.path, 'app', 'build', 'outputs', 'apk'));
+    return fs.directory(fs.path.join(directory.path, 'app', 'build', 'outputs', 'apk'));
   }
-  Directory _gradleAppOutV1Directory;
-
 
   bool isUsingGradle() {
     return directory.childFile('build.gradle').existsSync();
@@ -233,8 +219,7 @@
   }
 }
 
-/// Represents the contents of the .android-generated/ folder of a Flutter module
-/// project.
+/// Represents the contents of the .android/ folder of a Flutter module project.
 class AndroidModuleProject {
   AndroidModuleProject(this.directory);
 
@@ -243,9 +228,13 @@
   Future<void> ensureReadyForPlatformSpecificTooling(FlutterProject project) async {
     if (_shouldRegenerate()) {
       final Template template = new Template.fromName(fs.path.join('module', 'android'));
-      template.render(directory, <String, dynamic>{
-        'androidIdentifier': (await project.manifest).moduleDescriptor['androidPackage'],
-      }, printStatusWhenWriting: false);
+      template.render(
+        directory,
+        <String, dynamic>{
+          'androidIdentifier': project.manifest.moduleDescriptor['androidPackage'],
+        },
+        printStatusWhenWriting: false,
+      );
       gradle.injectGradleWrapper(directory);
     }
     await gradle.updateLocalProperties(project: project, requireAndroidSdk: false);
diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart
index a18ea9d..03ba79b 100644
--- a/packages/flutter_tools/lib/src/resident_runner.dart
+++ b/packages/flutter_tools/lib/src/resident_runner.dart
@@ -276,7 +276,7 @@
 
     if (package == null) {
       String message = 'No application found for $targetPlatform.';
-      final String hint = getMissingPackageHintForPlatform(targetPlatform);
+      final String hint = await getMissingPackageHintForPlatform(targetPlatform);
       if (hint != null)
         message += '\n$hint';
       printError(message);
@@ -335,7 +335,7 @@
 
     if (package == null) {
       String message = 'No application found for $targetPlatform.';
-      final String hint = getMissingPackageHintForPlatform(targetPlatform);
+      final String hint = await getMissingPackageHintForPlatform(targetPlatform);
       if (hint != null)
         message += '\n$hint';
       printError(message);
@@ -898,13 +898,13 @@
     return targetPath;
 }
 
-String getMissingPackageHintForPlatform(TargetPlatform platform) {
+Future<String> getMissingPackageHintForPlatform(TargetPlatform platform) async {
   switch (platform) {
     case TargetPlatform.android_arm:
     case TargetPlatform.android_arm64:
     case TargetPlatform.android_x64:
     case TargetPlatform.android_x86:
-      final FlutterProject project = new FlutterProject(fs.currentDirectory);
+      final FlutterProject project = await FlutterProject.current();
       final String manifestPath = fs.path.relative(project.android.gradleManifestFile.path);
       return 'Is your project missing an $manifestPath?\nConsider running "flutter create ." to create one.';
     case TargetPlatform.ios:
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart
index b37921f..d244f8d 100644
--- a/packages/flutter_tools/lib/src/runner/flutter_command.dart
+++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart
@@ -332,7 +332,8 @@
 
     if (shouldRunPub) {
       await pubGet(context: PubContext.getVerifyContext(name));
-      await new FlutterProject(fs.currentDirectory).ensureReadyForPlatformSpecificTooling();
+      final FlutterProject project = await FlutterProject.current();
+      await project.ensureReadyForPlatformSpecificTooling();
     }
 
     setupApplicationPackages();