When the flutter Module is modified, files in the.android and.ios directories will be accidentally overwritten. Yaml files and then execute the flutter packages get command. Android and. Ios directories will be replaced from the flutter template. Because we have our own gradle scripts in our.android directory (mainly to solve the problem of packaging aar); I don’t want this gradle to be overwritten;

The solution

  1. Modify the template in flutter- SDK to put gradle I wrote into the template.
  2. Find the performflutter packages getThe logic behind, by modifying the logic code, does not overwrite the existing code;

Replace the directory of the template

All template directories are under Flutter_HOME/packages/ Flutter_tools /templates:

Where the red arrows are above, is the template code I replaced and added; Ios should also be able to find templates to add and modify;

View the shell script command for FLUTTER

1. Start of the flutter command

Since this is the flutter command, we can look at the source of the flutter command; Open the FLUTTER_HOME/bin/flutter file with a text editor. The last line;

"$DART" --packages="$FLUTTER_TOOLS_DIR/.packages" $FLUTTER_TOOL_ARGS "$SNAPSHOT_PATH" "$@"
Copy the code

To observe printing (echo), run this command:

echo "$DART" --packages="$FLUTTER_TOOLS_DIR/.packages" $FLUTTER_TOOL_ARGS "$SNAPSHOT_PATH" "$@" 
Copy the code

Run the flutter –no-color packages get command to get the following:

/Users/xxxx/flutter/bin/cache/dart-sdk/bin/dart --packages=/Users/xxxx/flutter/packages/flutter_tools/.packages /Users/xxxx/flutter/bin/cache/flutter_tools.snapshot --no-color packages get
Copy the code

It is clear that he is executing from the file flutter_tools.snapshot; –no-color packages GET; So how is the flutter_tools.snapshot binary generated?

2. Generate the flutter_tools.snapshot file

Continue to look at the bin/flutter file;

"$DART" $FLUTTER_TOOL_ARGS --snapshot="$SNAPSHOT_PATH" --packages="$FLUTTER_TOOLS_DIR/.packages" "$SCRIPT_PATH"
Copy the code

This command is mainly used to compile flutter_tools.snapshot, we can print (echo) this command; Modify the shell script to go inside the if statement (see paragraph 3). The printed result looks like this;

/Users/xxxx/flutter/bin/cache/dart-sdk/bin/dart --snapshot=/Users/xxxx/flutter/bin/cache/flutter_tools.snapshot --packages=/Users/xxx/flutter/packages/flutter_tools/.packages /Users/xxxx/flutter/packages/flutter_tools/bin/flutter_tools.dart
Copy the code

Command from above we can see all the source mainly from/Users/XXXX/flutter/packages/flutter_tools directory inside here, go in to look at, is the dart source;

3. What are the conditions for compiling flutter_tools.snapshot

if [[ ! -f "$SNAPSHOT_PATH" || ! -s "$STAMP_PATH" || "$(cat "$STAMP_PATH")" ! = "$revision" || "$FLUTTER_TOOLS_DIR/pubspec.yaml" -nt "$FLUTTER_TOOLS_DIR/pubspec.lock" ]]; then echo Building flutter tool... fiCopy the code

Flutter_tools is compiled to generate flutter_tools.snapshot if one of the four conditions is met.

  • The flutter_tools.snapshot file does not exist
  • STAMP_PATH this file has a size of 0 and is used to cache a Git commit
  • Git commit is also triggered if the cached git commit and revision are different, revision =git rev-parse HEAD
  • ifpubspec.yamlThe file last modified time is greater thanpubspec.lockFile (NT: New Then)

After the above three points, we can now look at the source of Flutter_tools;

Check out the source code for Flutter_tools

It’s easier to import the source code into Android Studio. The main method starts with the flutter_tools/bin/flutter_tools.dart file; This class is very simple:

import 'package:flutter_tools/executable.dart' as executable;

void main(List<String> args) {
  executable.main(args);
}
Copy the code

So, all starts should be in executeable.dart; The main purpose of this document is to package all the commands into an object and register them in an array. Because we mainly observe the flutter packages get command, we will look at the PackagesCommand

In terms of class structure, it contains subcommands; PackagesGetCommand; No matter first; Because all FlutterCommands execute the Future

runCommand() method; So let’s look at the logic of this;

 @override
  Future<FlutterCommandResult> runCommand() async {
   / /... Omit unnecessary
    await _runPubGet(target);
    final FlutterProject rootProject = FlutterProject.fromPath(target);
    // This line of code is mainly used to refresh the.android and.ios directories
    await rootProject.ensureReadyForPlatformSpecificTooling(checkProjects: true);

    // Get/upgrade packages in example app as well
    if (rootProject.hasExampleApp) {
      final FlutterProject exampleProject = rootProject.example;
      await _runPubGet(exampleProject.directory.path);
      await exampleProject.ensureReadyForPlatformSpecificTooling(checkProjects: true);
    }
	// omit unnecessary}}Copy the code

Mainly in ensureReadyForPlatformSpecificTooling refresh logic

/// Generates project files necessary to make Gradle builds work on Android
  /// and CocoaPods+Xcode work on iOS, for app and module projects only.
  Future<void> ensureReadyForPlatformSpecificTooling({bool checkProjects = false}) async {
    if(! directory.existsSync() || hasExampleApp) {return;
    }
    refreshPluginsList(this); // Update the.flutter-plugin file here
    if((android.existsSync() && checkProjects) || ! checkProjects) {await android.ensureReadyForPlatformSpecificTooling();// Update here
    }
    if((ios.existsSync() && checkProjects) || ! checkProjects) {await ios.ensureReadyForPlatformSpecificTooling();// Update here
    }
    
    await injectPlugins(this, checkProjects: checkProjects);// Register some channels to the corresponding platform
  }
Copy the code
  • RefreshPluginsList (this) : refresh.flutter-pluginsfile
  • Android. EnsureReadyForPlatformSpecificTooling () : refresh. Android file
  • Await the ios. EnsureReadyForPlatformSpecificTooling () : refresh the ios file
  • InjectPlugins (this, checkProjects: checkProjects) : put some registered to the corresponding channel platform, GeneratedPluginRegistrant inside related code generation;

Can be seen from the above code, want to flutter package get not to refresh, to create the template, as long as the corresponding ensureReadyForPlatformSpecificTooling () code does not perform good; Then modify the source code, recompile; The compilation method is in the four ways of the FLUTTER script;