Flutter 安卓平台启动及初始化

image.png

flutter:跨平台(Android/iOS),图形引擎,Dart语言 这些都有什么关系呢
我们先看下在安卓平台下的初始化:
入口:manifest


    
    
        
            
            
            
            
            
                
                
            
        
        
        
    

我们看到没有 Application,只有一个 MainActivity,还有一堆 meta-data
接下来看下 MainActivity 做了什么

class MainActivity: FlutterActivity() {}

发现只是继承了 io.flutter 包下的FlutterActivity

public class FlutterActivity extends Activity implements Host, LifecycleOwner {

继承了 android.app.Activity 实现了LifecycleOwner 通过 LifecycleRegistry(this); 实现了一套 Lifecycler ,还有个 Host 接口 来扩展 Flutter 相关的功能,那么Flutter 引擎如何初始化的呢?发现 FlutterActivity 的 onCreate 执行了一些相关逻辑

protected void onCreate(@Nullable Bundle savedInstanceState) {
        this.switchLaunchThemeForNormalTheme();
        super.onCreate(savedInstanceState);
        this.lifecycle.handleLifecycleEvent(Event.ON_CREATE);
        this.delegate = new FlutterActivityAndFragmentDelegate(this);
        this.delegate.onAttach(this);
        this.delegate.onActivityCreated(savedInstanceState);
        this.configureWindowForTransparency();
        this.setContentView(this.createFlutterView());
        this.configureStatusBarForFullscreenFlutterExperience();
    }

1: 创建了 FlutterActivityAndFragmentDelegate 并 onAttach
2: 创建 FlutterView 通过 setContentView 添加到 Window
先看下第一步

void onAttach(@NonNull Context context) {
        this.ensureAlive();
        if (this.flutterEngine == null) {
            this.setupFlutterEngine();
        }
        this.platformPlugin = this.host.providePlatformPlugin(this.host.getActivity(), this.flutterEngine);
        if (this.host.shouldAttachEngineToActivity()) {
            Log.v("FlutterActivityAndFragmentDelegate", "Attaching FlutterEngine to the Activity that owns this Fragment.");
            this.flutterEngine.getActivityControlSurface().attachToActivity(this.host.getActivity(), this.host.getLifecycle());
        }
        this.host.configureFlutterEngine(this.flutterEngine);
    }

void setupFlutterEngine() {
        Log.v("FlutterActivityAndFragmentDelegate", "Setting up FlutterEngine.");
        String cachedEngineId = this.host.getCachedEngineId();
        if (cachedEngineId != null) {
            this.flutterEngine = FlutterEngineCache.getInstance().get(cachedEngineId);
            this.isFlutterEngineFromHost = true;
            if (this.flutterEngine == null) {
                throw new IllegalStateException("The requested cached FlutterEngine did not exist in the FlutterEngineCache: '" + cachedEngineId + "'");
            }
        } else {
            this.flutterEngine = this.host.provideFlutterEngine(this.host.getContext());
            if (this.flutterEngine != null) {
                this.isFlutterEngineFromHost = true;
            } else {
                Log.v("FlutterActivityAndFragmentDelegate", "No preferred FlutterEngine was provided. Creating a new FlutterEngine for this FlutterFragment.");
                this.flutterEngine = new FlutterEngine(this.host.getContext(), this.host.getFlutterShellArgs().toArray(), false, this.host.shouldRestoreAndSaveState());
                this.isFlutterEngineFromHost = false;
            }
        }
    }

setupFlutterEngin 方法去创建了 FlutterEngine 对象,这个对象是做什么到呢,我们看它到构造

public FlutterEngine(@NonNull Context context, @NonNull FlutterLoader flutterLoader, @NonNull FlutterJNI flutterJNI, @NonNull PlatformViewsController platformViewsController, @Nullable String[] dartVmArgs, boolean automaticallyRegisterPlugins, boolean waitForRestorationData) {
        this.engineLifecycleListeners = new HashSet();
        this.engineLifecycleListener = new FlutterEngine.EngineLifecycleListener() {
            public void onPreEngineRestart() {
                Log.v("FlutterEngine", "onPreEngineRestart()");
                Iterator var1 = FlutterEngine.this.engineLifecycleListeners.iterator();

                while(var1.hasNext()) {
                    FlutterEngine.EngineLifecycleListener lifecycleListener = (FlutterEngine.EngineLifecycleListener)var1.next();
                    lifecycleListener.onPreEngineRestart();
                }

                FlutterEngine.this.platformViewsController.onPreEngineRestart();
                FlutterEngine.this.restorationChannel.clearData();
            }
        };
        this.dartExecutor = new DartExecutor(flutterJNI, context.getAssets());
        this.dartExecutor.onAttachedToJNI();
        this.accessibilityChannel = new AccessibilityChannel(this.dartExecutor, flutterJNI);
        this.keyEventChannel = new KeyEventChannel(this.dartExecutor);
        this.lifecycleChannel = new LifecycleChannel(this.dartExecutor);
        this.localizationChannel = new LocalizationChannel(this.dartExecutor);
        this.mouseCursorChannel = new MouseCursorChannel(this.dartExecutor);
        this.navigationChannel = new NavigationChannel(this.dartExecutor);
        this.platformChannel = new PlatformChannel(this.dartExecutor);
        this.restorationChannel = new RestorationChannel(this.dartExecutor, waitForRestorationData);
        this.settingsChannel = new SettingsChannel(this.dartExecutor);
        this.systemChannel = new SystemChannel(this.dartExecutor);
        this.textInputChannel = new TextInputChannel(this.dartExecutor);
        this.localizationPlugin = new LocalizationPlugin(context, this.localizationChannel);
        this.flutterJNI = flutterJNI;
        flutterLoader.startInitialization(context.getApplicationContext());
        flutterLoader.ensureInitializationComplete(context, dartVmArgs);
        flutterJNI.addEngineLifecycleListener(this.engineLifecycleListener);
        flutterJNI.setPlatformViewsController(platformViewsController);
        flutterJNI.setLocalizationPlugin(this.localizationPlugin);
        this.attachToJni();
        this.renderer = new FlutterRenderer(flutterJNI);
        this.platformViewsController = platformViewsController;
        this.platformViewsController.onAttachedToJNI();
        this.pluginRegistry = new FlutterEnginePluginRegistry(context.getApplicationContext(), this, flutterLoader);
        if (automaticallyRegisterPlugins) {
            this.registerPlugins();
        }
    }

监听了引擎到变化,初始化了一些系统基础 Channel(Dart通道) , FlutterLoader 对象 start ,flutterJNI 对象初始化,FlutterRender及FlutterView初始化,registerPlugins(插件初始化)
先看下 FlutterLoader 的 startInitialization 方法吧 ensureInitializationComplete,这个是整个 Flutter引擎 初始化的基础:
startInitialization 方法

public void startInitialization(@NonNull Context applicationContext, @NonNull FlutterLoader.Settings settings) {
        if (this.settings == null) {
            if (Looper.myLooper() != Looper.getMainLooper()) {
                throw new IllegalStateException("startInitialization must be called on the main thread");
            } else {
                final Context appContext = applicationContext.getApplicationContext();
                this.settings = settings;
                this.initStartTimestampMillis = SystemClock.uptimeMillis();
                this.initConfig(appContext);
                VsyncWaiter.getInstance((WindowManager)appContext.getSystemService("window")).init();
                Callable initTask = new Callable() {
                    public FlutterLoader.InitResult call() {
                        ResourceExtractor resourceExtractor = FlutterLoader.this.initResources(appContext);
                        System.loadLibrary("flutter");
                        Executors.newSingleThreadExecutor().execute(new Runnable() {
                            public void run() {
                                FlutterJNI.nativePrefetchDefaultFontManager();
                            }
                        });
                        if (resourceExtractor != null) {
                            resourceExtractor.waitForCompletion();
                        }

                        return new FlutterLoader.InitResult(PathUtils.getFilesDir(appContext), PathUtils.getCacheDirectory(appContext), PathUtils.getDataDirectory(appContext));
                    }
                };
                this.initResultFuture = Executors.newSingleThreadExecutor().submit(initTask);
            }
        }
    }

初始化了 flutter 的 c 库,并将 安卓系统的 vsync 同步到 flutter

public void init() {
        FlutterJNI.setAsyncWaitForVsyncDelegate(this.asyncWaitForVsyncDelegate);
        float fps = this.windowManager.getDefaultDisplay().getRefreshRate();
        FlutterJNI.setRefreshRateFPS(fps);
    }

private final AsyncWaitForVsyncDelegate asyncWaitForVsyncDelegate = new AsyncWaitForVsyncDelegate() {
        public void asyncWaitForVsync(final long cookie) {
            Choreographer.getInstance().postFrameCallback(new FrameCallback() {
                public void doFrame(long frameTimeNanos) {
                    float fps = VsyncWaiter.this.windowManager.getDefaultDisplay().getRefreshRate();
                    long refreshPeriodNanos = (long)(1.0E9D / (double)fps);
                    FlutterJNI.nativeOnVsync(frameTimeNanos, frameTimeNanos + refreshPeriodNanos, cookie);
                }
            });
        }
    };

ensureInitializationComplete方法

public void ensureInitializationComplete(@NonNull Context applicationContext, @Nullable String[] args) {
        if (!this.initialized) {
            if (Looper.myLooper() != Looper.getMainLooper()) {
                throw new IllegalStateException("ensureInitializationComplete must be called on the main thread");
            } else if (this.settings == null) {
                throw new IllegalStateException("ensureInitializationComplete must be called after startInitialization");
            } else {
                try {
                    FlutterLoader.InitResult result = (FlutterLoader.InitResult)this.initResultFuture.get();
                    List shellArgs = new ArrayList();
                    shellArgs.add("--icu-symbol-prefix=_binary_icudtl_dat");
                    ApplicationInfo applicationInfo = this.getApplicationInfo(applicationContext);
                    shellArgs.add("--icu-native-lib-path=" + applicationInfo.nativeLibraryDir + File.separator + "libflutter.so");
                    if (args != null) {
                        Collections.addAll(shellArgs, args);
                    }

                    String kernelPath = null;
                    String snapshotAssetPath = result.dataDirPath + File.separator + this.flutterAssetsDir;
                    kernelPath = snapshotAssetPath + File.separator + "kernel_blob.bin";
                    shellArgs.add("--snapshot-asset-path=" + snapshotAssetPath);
                    shellArgs.add("--vm-snapshot-data=" + this.vmSnapshotData);
                    shellArgs.add("--isolate-snapshot-data=" + this.isolateSnapshotData);
                    shellArgs.add("--cache-dir-path=" + result.engineCachesPath);
                    if (this.settings.getLogTag() != null) {
                        shellArgs.add("--log-tag=" + this.settings.getLogTag());
                    }

                    long initTimeMillis = SystemClock.uptimeMillis() - this.initStartTimestampMillis;
                    Bundle bundle = applicationInfo.metaData;
                    if (bundle != null) {
                        boolean use_embedded_view = bundle.getBoolean("io.flutter.embedded_views_preview");
                        if (use_embedded_view) {
                            shellArgs.add("--use-embedded-view");
                        }
                    }

                    FlutterJNI.nativeInit(applicationContext, (String[])shellArgs.toArray(new String[0]), kernelPath, result.appStoragePath, result.engineCachesPath, initTimeMillis);
                    this.initialized = true;
                } catch (Exception var11) {
                    Log.e("FlutterLoader", "Flutter initialization failed.", var11);
                    throw new RuntimeException(var11);
                }
            }
        }
    }

加载 assets 下的资源, vm_snapshot_data 和 isolate_snapshot_data 并调用Nactive 方法 FlutterJNI.nativeInit 交给 Flutter 引擎

再回到 FlutterActivityAndFragmentDelegate 我们看下在 setContentView FlutterView 的创建:

View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Log.v("FlutterActivityAndFragmentDelegate", "Creating FlutterView.");
        this.ensureAlive();
        if (this.host.getRenderMode() == RenderMode.surface) {
            FlutterSurfaceView flutterSurfaceView = new FlutterSurfaceView(this.host.getActivity(), this.host.getTransparencyMode() == TransparencyMode.transparent);
            this.host.onFlutterSurfaceViewCreated(flutterSurfaceView);
            this.flutterView = new FlutterView(this.host.getActivity(), flutterSurfaceView);
        } else {
            FlutterTextureView flutterTextureView = new FlutterTextureView(this.host.getActivity());
            this.host.onFlutterTextureViewCreated(flutterTextureView);
            this.flutterView = new FlutterView(this.host.getActivity(), flutterTextureView);
        }

        this.flutterView.addOnFirstFrameRenderedListener(this.flutterUiDisplayListener);
        this.flutterSplashView = new FlutterSplashView(this.host.getContext());
        if (VERSION.SDK_INT >= 17) {
            this.flutterSplashView.setId(View.generateViewId());
        } else {
            this.flutterSplashView.setId(486947586);
        }

        this.flutterSplashView.displayFlutterViewWithSplash(this.flutterView, this.host.provideSplashScreen());
        Log.v("FlutterActivityAndFragmentDelegate", "Attaching FlutterEngine to FlutterView.");
        this.flutterView.attachToFlutterEngine(this.flutterEngine);
        return this.flutterSplashView;
    }

我们看到 contentView 是 FlutterSplashView 并调用了 displayFlutterViewWithSplash 方法

final class FlutterSplashView extends FrameLayout {
  
  public FlutterSplashView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.flutterEngineAttachmentListener = new FlutterEngineAttachmentListener() {
            public void onFlutterEngineAttachedToFlutterView(@NonNull FlutterEngine engine) {
                FlutterSplashView.this.flutterView.removeFlutterEngineAttachmentListener(this);
                FlutterSplashView.this.displayFlutterViewWithSplash(FlutterSplashView.this.flutterView, FlutterSplashView.this.splashScreen);
            }

            public void onFlutterEngineDetachedFromFlutterView() {
            }
        };
  ......
  public void displayFlutterViewWithSplash(@NonNull FlutterView flutterView, @Nullable SplashScreen splashScreen) {
        if (this.flutterView != null) {
            this.flutterView.removeOnFirstFrameRenderedListener(this.flutterUiDisplayListener);
            this.removeView(this.flutterView);
        }

        if (this.splashScreenView != null) {
            this.removeView(this.splashScreenView);
        }

        this.flutterView = flutterView;
        this.addView(flutterView);
        this.splashScreen = splashScreen;
        if (splashScreen != null) {
            if (this.isSplashScreenNeededNow()) {
                Log.v(TAG, "Showing splash screen UI.");
                this.splashScreenView = splashScreen.createSplashView(this.getContext(), this.splashScreenState);
                this.addView(this.splashScreenView);
                flutterView.addOnFirstFrameRenderedListener(this.flutterUiDisplayListener);
            } else if (this.isSplashScreenTransitionNeededNow()) {
                Log.v(TAG, "Showing an immediate splash transition to Flutter due to previously interrupted transition.");
                this.splashScreenView = splashScreen.createSplashView(this.getContext(), this.splashScreenState);
                this.addView(this.splashScreenView);
                this.transitionToFlutter();
            } else if (!flutterView.isAttachedToFlutterEngine()) {
                Log.v(TAG, "FlutterView is not yet attached to a FlutterEngine. Showing nothing until a FlutterEngine is attached.");
                flutterView.addFlutterEngineAttachmentListener(this.flutterEngineAttachmentListener);
            }
        }

    }

将 flutterView 和 SplashScreen(一个metadata 生成的 DrawableView)先后添加到 frameLayout 里,FlutterView 在 attachToFlutterEngine 时候回调将 SplashScreen 这个 View transitionToFlutter ,也就是 Alpha 设置为 0

 public void transitionToFlutter(@NonNull final Runnable onTransitionComplete) {
        if (this.splashView == null) {
            onTransitionComplete.run();
        } else {
            this.splashView.animate().alpha(0.0F).setDuration(this.crossfadeDurationInMillis).setListener(new AnimatorListener() {
                public void onAnimationStart(Animator animation) {
                }

                public void onAnimationEnd(Animator animation) {
                    onTransitionComplete.run();
                }

                public void onAnimationCancel(Animator animation) {
                    onTransitionComplete.run();
                }

                public void onAnimationRepeat(Animator animation) {
                }
            });
        }
    }

看了上面到源码感觉 flutter 引擎很像 WebView:


image.png

你可能感兴趣的:(Flutter 安卓平台启动及初始化)