Flutter启动流程和原理分析

Flutter是怎么启动起来的,是在Android的Activity的启动以后吗?等等这样的问题,在这个文章中将被解答。java

从MainActivity开始

新建立一个Flutter项目,在清单文件中默认被启动的Activity是MainActivity,而MainActivity继承的是FlutterActivity。那么问题好像简单了,咱们分析一下FlutterActivity,下面是MainActivity的代码。shell

public class MainActivity extends FlutterActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    GeneratedPluginRegistrant.registerWith(this);
  }
}
复制代码

上面的源码很简单,有两个点须要关注,第一个就是在MainActivity.onCreate()中调用了GeneratedPluginRegistrant.registerWith()这个方法,第二个是MainActivity继承自FlutterActivity,咱们对这两个关注点依次进行分析。json

GeneratedPluginRegistrant.registerWith()分析

咱们查看GeneratedPluginRegistrant,发现这个类是Android Studio自动生成的,而且不建议修改,这个类也很是简单,下面是GeneratedPluginRegistrant的代码。bash

public final class GeneratedPluginRegistrant {
  public static void registerWith(PluginRegistry registry) {
    if (alreadyRegisteredWith(registry)) {
      return;
    }
  }

  private static boolean alreadyRegisteredWith(PluginRegistry registry) {
    final String key = GeneratedPluginRegistrant.class.getCanonicalName();
    if (registry.hasPlugin(key)) {
      return true;
    }
    registry.registrarFor(key);
    return false;
  }
}
复制代码

若是PluginRegistry已经包含了GeneratedPluginRegistrant就直接返回true,如没有就调用PluginRegistry.registrarFor()进行注册。app

咱们分析一下PluginRegistry,看看是怎么注册的,发现PluginRegistry是一个接口,下面是PluginRegistry的代码。ide

public interface PluginRegistry {
    Registrar registrarFor(String pluginKey);
}
复制代码

PluginRegistry的实现是谁呢?是FlutterActivity,下面开发分析FlutterActivity,暂时看FlutterActivity比较重要,由于这个类是MainActivity的父类,仍是PluginRegistry的具体实现类。oop

FlutterActivity分析

下面是FlutterActivity的代码。this

public class FlutterActivity extends Activity implements FlutterView.Provider, PluginRegistry, ViewFactory {
    private final FlutterActivityDelegate delegate = new FlutterActivityDelegate(this, this);
  
    private final FlutterActivityEvents eventDelegate = delegate;
    private final FlutterView.Provider viewProvider = delegate;
    private final PluginRegistry pluginRegistry = delegate;
  
    @Override
    public final boolean hasPlugin(String key) {
        return pluginRegistry.hasPlugin(key);
    }

    @Override
    public final Registrar registrarFor(String pluginKey) {
        return pluginRegistry.registrarFor(pluginKey);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        eventDelegate.onCreate(savedInstanceState);
    }

    @Override
    protected void onDestroy() {
        eventDelegate.onDestroy();
        super.onDestroy();
    }
  
  	@Override
    protected void onStop() {
        eventDelegate.onStop();
        super.onStop();
    }
    //省略了一些代码
}

复制代码

从上面的代码中能够看出来,FlutterActivity是继承Activity和实现了PluginRegistry。分析一下onCreate,onStop,onDestroy这些生命周期方法被FlutterActivity.eventDelegate代理了,这个时候咱们明白了,FlutterActivity就是一个空壳,真正实现是代理类FlutterActivityDelegate。spa

咱们具体看一下,下面是FlutterActivity.onCreate()的代码。线程

@Override
 protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     eventDelegate.onCreate(savedInstanceState);
 }
复制代码

FlutterActivity.$onCreate()比较简单,调用了super的onCreate()和eventDelegate.onCreate(),也就是调用了代理类的onCreate方法,下面分析FlutterActivityDelegate。

FlutterActivityDelegate分析

从上面的分析能够得出结论,FlutterActivity什么都没有作,都交个了FlutterActivityDelegate去干,这里类实现了PluginRegistry,下面是FlutterActivityDelegate的代码。

public final class FlutterActivityDelegate implements FlutterActivityEvents, FlutterView.Provider, PluginRegistry {
		@Override
    public void onCreate(Bundle savedInstanceState) {
      
    }                     
}

复制代码

仍是先分析FlutterActivityDelegate.onCreate(),这个真正干活的onCreate方法仍是比较复杂的,下面是FlutterActivityDelegate.onCreate()的代码。

@Override
public void onCreate(Bundle savedInstanceState) {
    String[] args = getArgsFromIntent(activity.getIntent());//1
    FlutterMain.ensureInitializationComplete(activity.getApplicationContext(), args);//2
    flutterView = viewFactory.createFlutterView(activity);//3
    if (flutterView == null) {
        FlutterNativeView nativeView = viewFactory.createFlutterNativeView();
        flutterView = new FlutterView(activity, null, nativeView);//4
        flutterView.setLayoutParams(matchParent);
        activity.setContentView(flutterView);//5
        launchView = createLaunchView();
        if (launchView != null) {
            addLaunchView();
        }
    }
    if (loadIntent(activity.getIntent())) {
        return;
    }
    String appBundlePath = FlutterMain.findAppBundlePath(activity.getApplicationContext());
    if (appBundlePath != null) {
        runBundle(appBundlePath);
    }
}
复制代码
注释1

获得了一些参数,这些参数是干啥用的?咱们拿一个trace-startup参数为例进行简单介绍下面是FlutterActivityDelegate.getArgsFromIntent()的代码。

private static String[] getArgsFromIntent(Intent intent) {
    ArrayList<String> args = new ArrayList<>();
    if (intent.getBooleanExtra("trace-startup", false)) {
        args.add("--trace-startup");
    }
    if (intent.getBooleanExtra("start-paused", false)) {
        args.add("--start-paused");
    }
  
    if (!args.isEmpty()) {
        String[] argsArray = new String[args.size()];
        return args.toArray(argsArray);
    }
    return null;
}
复制代码

当你安装一个App的时候,能够用下面这个命令,

flutter run --trace-startup --profile
复制代码

安装完以后会生下面这个json,

{
  "engineEnterTimestampMicros": 273508186457,
  "timeToFrameworkInitMicros": 271420,
  "timeToFirstFrameMicros": 469796,
  "timeAfterFrameworkInitMicros": 198376
}
复制代码

这个json会显示进入Flutter引擎的时间和展现应用第一帧的时间等等。

注释2

调用 FlutterMain.ensureInitializationComplete(),这方法初始化了Flutter,下面是ensureInitializationComplete的代码。

public static void ensureInitializationComplete(Context applicationContext, String[] args) {
        if (Looper.myLooper() != Looper.getMainLooper()) {
          throw new IllegalStateException("ensureInitializationComplete must be called on the main thread");
        }
        try {
            sResourceExtractor.waitForCompletion();
            List<String> shellArgs = new ArrayList<>();
            shellArgs.add("--icu-symbol-prefix=_binary_icudtl_dat");
    
            String appBundlePath = findAppBundlePath(applicationContext);
            String appStoragePath = PathUtils.getFilesDir(applicationContext);
          
            nativeInit(applicationContext, shellArgs.toArray(new String[0]),
                appBundlePath, appStoragePath, engineCachesPath);//1
        } catch (Exception e) {
            Log.e(TAG, "Flutter initialization failed.", e);
            throw new RuntimeException(e);
        }
    }

		//native方法
    private static native void nativeInit(Context context, String[] args, String bundlePath, String appStoragePath, String engineCachesPath);
复制代码

先判断是否是主线程,若是不是主线程直接抛出异常。初始化参数调用 FlutterMain.nativeInit()方法,这个方法是native方法,主要的用途是初始化Flutter。

注释3

ViewFactory是一个接口,ViewFactory.createFlutterView()的具体实现有两个,分别是FlutterActivity.createFlutterView()和FlutterFragmentActivity.createFlutterView()如今这个两个具体实现都返回null,也就是必定会走到注释4。

注释4

建立FlutterView,那么FlutterView是什么呢?看一下类的声明,下面是FlutterView的声明的代码,

public class FlutterView extends SurfaceView implements BinaryMessenger, TextureRegistry } 复制代码

原来是一 SurfaceView,这个就很容易理解了。

注释5

关键来了,下面是调用setContentView的代码,

activity.setContentView(flutterView);
复制代码

把FlutterView加载到Activity中,折腾了半天,就是作了这样一件事,说白了就是建立了一个FlutterView,而且把这个view显示到屏幕上。

下面是Flutter的启动流程图。

相关文章
相关标签/搜索