<application android:name="io.flutter.app.FlutterApplication" android:label="free_ctrip" android:icon="@mipmap/ic_launcher"> <activity android:name=".MainActivity" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize"> <!-- This keeps the window background of the activity showing until Flutter renders its first frame. It can be removed if there is no splash screen (such as the default splash screen defined in @style/LaunchTheme). --> <meta-data android:name="io.flutter.app.android.SplashScreenUntilFirstFrame" android:value="true" /> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application>
publicvoidstartInitialization(@NonNull Context applicationContext, @NonNull Settings settings) { // Do not run startInitialization more than once. // 多次调用的判断 if (this.settings != null) { return; } // 保证主线程启动 if (Looper.myLooper() != Looper.getMainLooper()) { thrownewIllegalStateException("startInitialization must be called on the main thread"); } // 暂存设置对象 this.settings = settings; // 启动计时 longinitStartTimestampMillis= SystemClock.uptimeMillis(); // 初始化源数据配置 initConfig(applicationContext); // 初始化资源文件 initResources(applicationContext); // 加载flutter.so flutter引擎 System.loadLibrary("flutter");
// We record the initialization time using SystemClock because at the start of the // initialization we have not yet loaded the native library to call into dart_tools_api.h. // To get Timeline timestamp of the start of initialization we simply subtract the delta // from the Timeline timestamp at the current moment (the assumption is that the overhead // of the JNI call is negligible). longinitTimeMillis= SystemClock.uptimeMillis() - initStartTimestampMillis; // 为什么Native层要记录这个启动的时间差?? FlutterJNI.nativeRecordStartTimestamp(initTimeMillis); }
// There isn't a `<meta-data>` tag as a direct child of `<application>` in // `AndroidManifest.xml`. if (metadata == null) { return; } // 这些源数据的解析,我们后续分析 aotSharedLibraryName = metadata.getString(PUBLIC_AOT_SHARED_LIBRARY_NAME, DEFAULT_AOT_SHARED_LIBRARY_NAME); flutterAssetsDir = metadata.getString(PUBLIC_FLUTTER_ASSETS_DIR_KEY, DEFAULT_FLUTTER_ASSETS_DIR);
/** * Extract assets out of the APK that need to be cached as uncompressed * files on disk. */ privatevoidinitResources(@NonNull Context applicationContext) { // 先清空资源 newResourceCleaner(applicationContext).start(); // 只在DEBUG或者JIT_RELEASE模式下执行 if (BuildConfig.DEBUG || BuildConfig.JIT_RELEASE) { finalStringdataDirPath= PathUtils.getDataDirectory(applicationContext); finalStringpackageName= applicationContext.getPackageName(); finalPackageManagerpackageManager= applicationContext.getPackageManager(); finalAssetManagerassetManager= applicationContext.getResources().getAssets(); resourceExtractor = newResourceExtractor(dataDirPath, packageName, packageManager, assetManager);
// In debug/JIT mode these assets will be written to disk and then // mapped into memory so they can be provided to the Dart VM. // 虚拟机快照数据?? // 隔离快照数据 resourceExtractor .addResource(fullAssetPathFrom(vmSnapshotData)) .addResource(fullAssetPathFrom(isolateSnapshotData)) .addResource(fullAssetPathFrom(DEFAULT_KERNEL_BLOB));
// When "retain instance" is true, the FlutterEngine will survive configuration // changes. Therefore, we create a new one only if one does not already exist. if (flutterEngine == null) { // Flutter引擎的创建以及实例化 setupFlutterEngine(); }
if (host.shouldAttachEngineToActivity()) { Log.d(TAG, "Attaching FlutterEngine to the Activity that owns this Fragment."); flutterEngine.getActivityControlSurface().attachToActivity( host.getActivity(), host.getLifecycle() ); }
/* package */ void setupFlutterEngine() { Log.d(TAG, "Setting up FlutterEngine.");
// First, check if the host wants to use a cached FlutterEngine. // 首先检查Host是否需要使用缓存的引擎。 // 这个就是我们为什么要构建缓存引擎的时候一定要传ID的原因 String cachedEngineId = host.getCachedEngineId(); if (cachedEngineId != null) { // 从引擎池里面取出引擎 flutterEngine = FlutterEngineCache.getInstance().get(cachedEngineId); isFlutterEngineFromHost = true; if (flutterEngine == null) { throw new IllegalStateException("The requested cached FlutterEngine did not exist in the FlutterEngineCache: '" + cachedEngineId + "'"); } return; } // 很好理解,上面如果已经有了缓冲引擎池,那么下面我们就不需要构建了。 // Second, defer to subclasses for a custom FlutterEngine. // 第二步,再检查host提供的flutter的引擎 flutterEngine = host.provideFlutterEngine(host.getContext()); if (flutterEngine != null) { isFlutterEngineFromHost = true; return; }
// Our host did not provide a custom FlutterEngine. Create a FlutterEngine to back our // FlutterView. Log.d(TAG, "No preferred FlutterEngine was provided. Creating a new FlutterEngine for" + " this FlutterFragment."); // 只有不使用缓存的FlutterEngine.也不使用flutterActivity提供的FlutterEngine。 // FlutterEngine才在最后一步创建 flutterEngine = new FlutterEngine(host.getContext(), host.getFlutterShellArgs().toArray()); isFlutterEngineFromHost = false; }
// TODO(mattcarroll): FlutterRenderer is temporally coupled to attach(). Remove that coupling if possible. this.renderer = new FlutterRenderer(flutterJNI);
accessibilityChannel = new AccessibilityChannel(dartExecutor, flutterJNI); keyEventChannel = new KeyEventChannel(dartExecutor); lifecycleChannel = new LifecycleChannel(dartExecutor); localizationChannel = new LocalizationChannel(dartExecutor); navigationChannel = new NavigationChannel(dartExecutor); platformChannel = new PlatformChannel(dartExecutor); settingsChannel = new SettingsChannel(dartExecutor); systemChannel = new SystemChannel(dartExecutor); textInputChannel = new TextInputChannel(dartExecutor);
platformViewsController = new PlatformViewsController(); // 实例化pluginRegistry。传入的参数有context this.pluginRegistry = new FlutterEnginePluginRegistry( context.getApplicationContext(), this, flutterLoader ); // 判断是否需要自动注入plugins if (automaticallyRegisterPlugins) { registerPlugins(); } }
/** * Blocks until initialization of the native system has completed. * <p> * Calling this method multiple times has no effect. * * @param applicationContext The Android application context. * @param args Flags sent to the Flutter runtime. */ public void ensureInitializationComplete(@NonNull Context applicationContext, @Nullable String[] args) { // 用一个标志变量来标记是否初始化过 if (initialized) { return; } // 保证主线程的调用 if (Looper.myLooper() != Looper.getMainLooper()) { throw new IllegalStateException("ensureInitializationComplete must be called on the main thread"); } // 保证必须调用过startInitialization()方法 if (settings == null) { throw new IllegalStateException("ensureInitializationComplete must be called after startInitialization"); } try { // 只有在DEBUG或者JIT_RELEASE模式下resourceExtractor才非空 if (resourceExtractor != null) { resourceExtractor.waitForCompletion(); } //初始化shell参数 List<String> shellArgs = new ArrayList<>(); shellArgs.add("--icu-symbol-prefix=_binary_icudtl_dat");
// Most devices can load the AOT shared library based on the library name // with no directory path. Provide a fully qualified path to the library // as a workaround for devices where that fails. //这里很重要,如果libapp.so加载失败,可以设置libapp.so的全路径 shellArgs.add("--" + AOT_SHARED_LIBRARY_NAME + "=" + applicationInfo.nativeLibraryDir + File.separator + aotSharedLibraryName); }