Flutter启动流程

作者: 881ef7b85f62 | 来源:发表于2019-04-12 20:47 被阅读3次

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

    从MainActivity开始

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

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

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

    GeneratedPluginRegistrant.registerWith()分析

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

    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()进行注册。

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

    public interface PluginRegistry {
        Registrar registrarFor(String pluginKey);
    }
    

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

    FlutterActivity分析

    下面是FlutterActivity的代码。

    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。

    我们具体看一下,下面是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的启动流程图。


    关于Flutter的全部学习内容,我们这边都有系统的知识体系以及进阶视频资料,有需要的朋友可以加群免费领取安卓进阶视频教程,源码,面试资料,群内有大牛一起交流讨论技术;点击链接加入群聊【腾讯@Android高级架构】
    (包括自定义控件、NDK、架构设计、混合式开发工程师(React native,Weex)、性能优化、完整商业项目开发等)

    Android高级进阶视频教程

    相关文章

      网友评论

        本文标题:Flutter启动流程

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