美文网首页flutterFlutter圈子
Flutter 热更新-1.12.13+hotfix.5启动流程

Flutter 热更新-1.12.13+hotfix.5启动流程

作者: 折剑游侠 | 来源:发表于2019-12-19 16:59 被阅读0次

    这里分析flutter作为module情况下Android端启动流程。

    1.12.13版本通过下述方法启动Flutter页面。

    startActivity(
       FlutterActivity.createDefaultIntent(this)
    )
    

    createDefaultIntent()

    public static Intent createDefaultIntent(@NonNull Context launchContext) {
      return withNewEngine().build(launchContext);
    }
    
    public Intent build(@NonNull Context context) {
      return new Intent(context, activityClass)
          .putExtra(EXTRA_INITIAL_ROUTE, initialRoute)
          .putExtra(EXTRA_BACKGROUND_MODE, backgroundMode)
          .putExtra(EXTRA_DESTROY_ENGINE_WITH_ACTIVITY, true);
    }
     
    //activityClass声明处Class<? extends FlutterActivity>
    //activityClass是FlutterActivity的子类型,接下来看FlutterActivity.onCreate()
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
      switchLaunchThemeForNormalTheme();
     
      super.onCreate(savedInstanceState);
     
      lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
     
      delegate = new FlutterActivityAndFragmentDelegate(this);
      delegate.onAttach(this);
      delegate.onActivityCreated(savedInstanceState);
     
      configureWindowForTransparency();
      setContentView(createFlutterView());
      configureStatusBarForFullscreenFlutterExperience();
    }
    

    delegate.onAttach(this)
    delegate.onActivityCreated(savedInstanceState)

    FlutterActivityAndFragmentDelegate.onActivityCreated()

    void onActivityCreated(@Nullable Bundle bundle) {
      Log.v(TAG, "onActivityCreated. Giving plugins an opportunity to restore state.");
      ensureAlive();
     
      if (host.shouldAttachEngineToActivity()) {
        flutterEngine.getActivityControlSurface().onRestoreInstanceState(bundle);
      }
    }
    

    flutterEngine.getActivityControlSurface().onRestoreInstanceState最终调用到

    FlutterEnginePluginRegistry.onRestoreInstanceState()

    public void onRestoreInstanceState(@Nullable Bundle bundle) {
      if (isAttachedToActivity()) {
        activityPluginBinding.onRestoreInstanceState(bundle);
      } else {
        Log.e(TAG, "Attempted to notify ActivityAware plugins of onRestoreInstanceState, but no Activity was attached.");
      }
    }
    

    activityPluginBinding.onRestoreInstanceState(bundle)

    activityPluginBinding是FlutterEnginePluginRegistry的静态内部类FlutterEngineActivityPluginBinding

    FlutterEngineActivityPluginBinding.onRestoreInstanceState()

    遍历OnSaveInstanceStateListener集合回调onRestoreInstanceState()方法

    void onRestoreInstanceState(@Nullable Bundle bundle) {
      for (OnSaveInstanceStateListener listener : onSaveInstanceStateListeners) {
        listener.onRestoreInstanceState(bundle);
      }
    }
    

    onSaveInstanceStateListeners是FlutterEngineActivityPluginBinding成员变量

    private final Set<OnSaveInstanceStateListener> onSaveInstanceStateListeners = new HashSet<>();
    

    看看它在哪里被赋值,还是FlutterEngineActivityPluginBinding中

    @Override
    public void addOnSaveStateListener(@NonNull OnSaveInstanceStateListener listener) {
      onSaveInstanceStateListeners.add(listener);
    }
    

    addOnSaveStateListener是ActivityPluginBinding接口方法

    FlutterEngine通过FlutterEnginePluginRegistry注册一些PluginBinding同步对应组件的信息

    ActivityPluginBinding中就有我们很熟悉的一些Activity回调

    类似的FlutterEnginePluginRegistry中FlutterEngineServicePluginBinding实现了ServicePluginBinding接口

    public interface ActivityPluginBinding {
      @NonNull
      Activity getActivity();
    
      @NonNull
      Object getLifecycle();
    
      void addRequestPermissionsResultListener(@NonNull PluginRegistry.RequestPermissionsResultListener listener);
    
      void removeRequestPermissionsResultListener(@NonNull PluginRegistry.RequestPermissionsResultListener listener);
    
      void addActivityResultListener(@NonNull PluginRegistry.ActivityResultListener listener);
    
      void removeActivityResultListener(@NonNull PluginRegistry.ActivityResultListener listener);
    
      void addOnNewIntentListener(@NonNull PluginRegistry.NewIntentListener listener);
    
      void removeOnNewIntentListener(@NonNull PluginRegistry.NewIntentListener listener);
    
      void addOnUserLeaveHintListener(@NonNull PluginRegistry.UserLeaveHintListener listener);
    
      void removeOnUserLeaveHintListener(@NonNull PluginRegistry.UserLeaveHintListener listener);
    
      void addOnSaveStateListener(@NonNull OnSaveInstanceStateListener listener);
    
      void removeOnSaveStateListener(@NonNull OnSaveInstanceStateListener listener);
    
      interface OnSaveInstanceStateListener {
        void onSaveInstanceState(@NonNull Bundle bundle);
    
        void onRestoreInstanceState(@Nullable Bundle bundle);
      }
    }
    

    FlutterActivityAndFragmentDelegate.onAttach()

    void onAttach(@NonNull Context context) {
      ensureAlive();
     
      if (flutterEngine == null) {
        setupFlutterEngine();
      }
     
      platformPlugin = host.providePlatformPlugin(host.getActivity(), flutterEngine);
     
      if (host.shouldAttachEngineToActivity()) {
        //FlutterEnginePluginRegistry.attachToActivity()
        flutterEngine.getActivityControlSurface().attachToActivity(
            host.getActivity(),
            host.getLifecycle()
        );
      }
     
      host.configureFlutterEngine(flutterEngine);
    }
    

    ensureAlive()

    private void ensureAlive() {
        //host是前面delegate = new FlutterActivityAndFragmentDelegate(this)传入的this即FlutterActivity
        if (host == null) {
          throw new IllegalStateException("Cannot execute method on a destroyed FlutterActivityAndFragmentDelegate.");
        }
      }
    

    setupFlutterEngine()

    void setupFlutterEngine() {
      String cachedEngineId = host.getCachedEngineId();
      if (cachedEngineId != null) {
        //flutterEngine缓存池
        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;
      }
     
      flutterEngine = host.provideFlutterEngine(host.getContext());
      if (flutterEngine != null) {
        isFlutterEngineFromHost = true;
        return;
      }
     
      //初始化FlutterEngine
      flutterEngine = new FlutterEngine(host.getContext(), host.getFlutterShellArgs().toArray());
      isFlutterEngineFromHost = false;
    }
    

    FlutterEngine()

    public FlutterEngine(@NonNull Context context, @Nullable String[] dartVmArgs) {
      this(context, FlutterLoader.getInstance(), new FlutterJNI(), dartVmArgs, true);
    }
    
    public FlutterEngine(
        @NonNull Context context,
        @NonNull FlutterLoader flutterLoader,
        @NonNull FlutterJNI flutterJNI,
        @Nullable String[] dartVmArgs,
        boolean automaticallyRegisterPlugins
    ) {
      this.flutterJNI = flutterJNI;
      flutterLoader.startInitialization(context);
      flutterLoader.ensureInitializationComplete(context, dartVmArgs);
     
      flutterJNI.addEngineLifecycleListener(engineLifecycleListener);
      attachToJni();
     
      this.dartExecutor = new DartExecutor(flutterJNI, context.getAssets());
      this.dartExecutor.onAttachedToJNI();
     
      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();
     
      this.pluginRegistry = new FlutterEnginePluginRegistry(
        context.getApplicationContext(),
        this,
        flutterLoader
      );
     
      if (automaticallyRegisterPlugins) {
        registerPlugins();
      }
    }
    

    flutterLoader.startInitialization(context)
    flutterLoader.ensureInitializationComplete(context, dartVmArgs)

    FlutterLoader.startInitialization()

    public void startInitialization(@NonNull Context applicationContext) {
            startInitialization(applicationContext, new Settings());
    }
    public void startInitialization(@NonNull Context applicationContext, @NonNull Settings settings) {
            if (this.settings != null) {
              return;
            }
            if (Looper.myLooper() != Looper.getMainLooper()) {
              throw new IllegalStateException("startInitialization must be called on the main thread");
            }
    
            this.settings = settings;
    
            long initStartTimestampMillis = SystemClock.uptimeMillis();
            initConfig(applicationContext);
            initResources(applicationContext);
    
            System.loadLibrary("flutter");
    
            VsyncWaiter
                .getInstance((WindowManager) applicationContext.getSystemService(Context.WINDOW_SERVICE))
                .init();
    
            long initTimeMillis = SystemClock.uptimeMillis() - initStartTimestampMillis;
            FlutterJNI.nativeRecordStartTimestamp(initTimeMillis);
    }
    
    //initConfig 初始化资源文件
    private void initConfig(@NonNull Context applicationContext) {
            Bundle metadata = getApplicationInfo(applicationContext).metaData;
    
            if (metadata == null) {
                return;
            }
    
            //so包名称
            aotSharedLibraryName = metadata.getString(PUBLIC_AOT_SHARED_LIBRARY_NAME, DEFAULT_AOT_SHARED_LIBRARY_NAME);
            //flutterAsset
            flutterAssetsDir = metadata.getString(PUBLIC_FLUTTER_ASSETS_DIR_KEY, DEFAULT_FLUTTER_ASSETS_DIR);
            //BuildConfig.DEBUG || BuildConfig.JIT_RELEASE使用,AOT Release版本flutter代码打包成so包。
            //ensureInitializationComplete()中可以验证
            vmSnapshotData = metadata.getString(PUBLIC_VM_SNAPSHOT_DATA_KEY, DEFAULT_VM_SNAPSHOT_DATA);
            isolateSnapshotData = metadata.getString(PUBLIC_ISOLATE_SNAPSHOT_DATA_KEY, DEFAULT_ISOLATE_SNAPSHOT_DATA);
    }
    //initResources 初始化资源,方法名自解释。
    private void initResources(@NonNull Context applicationContext) {
            new ResourceCleaner(applicationContext).start();
    
            if (BuildConfig.DEBUG || BuildConfig.JIT_RELEASE) {
                final String dataDirPath = PathUtils.getDataDirectory(applicationContext);
                final String packageName = applicationContext.getPackageName();
                final PackageManager packageManager = applicationContext.getPackageManager();
                final AssetManager assetManager = applicationContext.getResources().getAssets();
                resourceExtractor = new ResourceExtractor(dataDirPath, packageName, packageManager, assetManager);
    
                resourceExtractor
                    .addResource(fullAssetPathFrom(vmSnapshotData))
                    .addResource(fullAssetPathFrom(isolateSnapshotData))
                    .addResource(fullAssetPathFrom(DEFAULT_KERNEL_BLOB));
    
                resourceExtractor.start();
            }
    }
    

    ensureInitializationComplete()

    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");
        }
        if (settings == null) {
          throw new IllegalStateException("ensureInitializationComplete must be called after startInitialization");
        }
        try {
            if (resourceExtractor != null) {
                resourceExtractor.waitForCompletion();
            }
     
            List<String> shellArgs = new ArrayList<>();
            shellArgs.add("--icu-symbol-prefix=_binary_icudtl_dat");
     
            ApplicationInfo applicationInfo = getApplicationInfo(applicationContext);
            shellArgs.add("--icu-native-lib-path=" + applicationInfo.nativeLibraryDir + File.separator + DEFAULT_LIBRARY);
     
            if (args != null) {
                Collections.addAll(shellArgs, args);
            }
     
            String kernelPath = null;
            //DEBUG/JIT_RELEASE加载逻辑
            if (BuildConfig.DEBUG || BuildConfig.JIT_RELEASE) {
                String snapshotAssetPath = PathUtils.getDataDirectory(applicationContext) + File.separator + flutterAssetsDir;
                kernelPath = snapshotAssetPath + File.separator + DEFAULT_KERNEL_BLOB;
                shellArgs.add("--" + SNAPSHOT_ASSET_PATH_KEY + "=" + snapshotAssetPath);
                shellArgs.add("--" + VM_SNAPSHOT_DATA_KEY + "=" + vmSnapshotData);
                shellArgs.add("--" + ISOLATE_SNAPSHOT_DATA_KEY + "=" + isolateSnapshotData);
            } else {//AOT Release加载逻辑
                shellArgs.add("--" + AOT_SHARED_LIBRARY_NAME + "=" + aotSharedLibraryName);
    
                //热更新可指定AOT_SHARED_LIBRARY_NAME为hotfix.so地址
                //hotfix.so拷贝到data/data/package/app_libs/目录下
                shellArgs.add("--" + AOT_SHARED_LIBRARY_NAME + "=" + applicationInfo.nativeLibraryDir + File.separator + aotSharedLibraryName);
            }
     
            shellArgs.add("--cache-dir-path=" + PathUtils.getCacheDirectory(applicationContext));
            if (settings.getLogTag() != null) {
                shellArgs.add("--log-tag=" + settings.getLogTag());
            }
     
            String appStoragePath = PathUtils.getFilesDir(applicationContext);
            String engineCachesPath = PathUtils.getCacheDirectory(applicationContext);
            FlutterJNI.nativeInit(applicationContext, shellArgs.toArray(new String[0]),
                kernelPath, appStoragePath, engineCachesPath);
     
            initialized = true;
        } catch (Exception e) {
            Log.e(TAG, "Flutter initialization failed.", e);
            throw new RuntimeException(e);
        }
    }
    

    shellArgs.add("--" + AOT_SHARED_LIBRARY_NAME + "=" + aotSharedLibraryName)

    shellArgs是个数组,包含so包和资源文件,最终调用FlutterJNI.nativeInit()加载flutter资源。

    实现热更新可以从这个数组入手。

    相关文章

      网友评论

        本文标题:Flutter 热更新-1.12.13+hotfix.5启动流程

        本文链接:https://www.haomeiwen.com/subject/bufvnctx.html