安卓平台Flutter启动过程全解析

前言

今天主要带大家一起分析下flutter是如何启动、初始化和加载dart代码的。这里有几点需要提前告知:

  1. 由于篇幅的问题,关于flutter界面创建、绘制过程将略过;

  2. 由于相关的c++代码比较多,而且较为复杂,建议先下载flutter engine的完整开发环境代码,阅读本文更方便;

  3. 本文只分析启动过程,参考的项目是基于android studio创建的一个默认flutter项目,以下简称demo。
    (文章干货很长 请耐心看完 文末有福利!)

正文

java层启动过程

熟悉android的朋友都知道,一个APP启动会先执行Application再执行Activity(AndroidManifest.xml中配置的启动Activity),结合这个,我们先看看Application里做了什么,在分析过程中我们将挑取一些关键的native方法作为c++层入口方法作进一步的分析。

// io.flutter.app.FlutterApplication
public class FlutterApplication extends Application {
    @Override
    @CallSuper
    public void onCreate() {
        super.onCreate();
        FlutterMain.startInitialization(this);
    }

    //这块代码和FlutterActivityDelegate的生命周期方法结合使用
    private Activity mCurrentActivity = null;
    public Activity getCurrentActivity() {
        return mCurrentActivity;
    }
    public void setCurrentActivity(Activity mCurrentActivity) {
        this.mCurrentActivity = mCurrentActivity;
    }
}

// io.flutter.view.FlutterMain中的方法
public static void startInitialization(Context applicationContext, FlutterMain.Settings settings) {
    if (Looper.myLooper() != Looper.getMainLooper()) {
        throw new IllegalStateException("startInitialization must be called on the main thread");
    } else if (sSettings == null) {
        sSettings = settings;
        long initStartTimestampMillis = SystemClock.uptimeMillis();
        initConfig(applicationContext);
        initAot(applicationContext);
        initResources(applicationContext);
        System.loadLibrary("flutter");
       ...
    }
}

startInitialization只能执行在主线程中,否则会抛出异常。通过sSettings这个变量可以看出,启动的过程中,这个方法将只执行一遍。initConfig初始化一些变量的配置信息(在AndroidManifest.xml中可以通过meta-data方式配置这些变量值), System.loadLibrary("flutter")则完成装载flutter库文件,期间会在c++层完成JNI方法的动态注册。initResources方法我们往下看。

private static void initResources(Context applicationContext) {
    Context context = applicationContext;
    new ResourceCleaner(context).start();
    ...
    sResourceExtractor = new ResourceExtractor(context);
    ...
    sResourceExtractor.start();
}

ResourceCleaner将清理带有指定标识的缓存文件,ResourceExtractor将完成asset 目录下flutter相关资源的拷贝,这些资源会在后续flutter engine和DartVM等初始化时使用。 然后我们再来看看启动activity都做了些什么

onCreate

//MainActivity.java

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

//FlutterActivity.java

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

先看FlutterActivity中执行onCreate,可以看到这里面并没有当前ContentView的设置,那么其内容界面是在哪里设置的呢,我们可以看到第二句this.eventDelegate.onCreate(savedInstanceState);,最终我们发现Activity中显示的view是在代理类中进行初始化的,下面看下代理类FlutterActivityDelegate的执行,

//FlutterActivityDelegate.java

public void onCreate(Bundle savedInstanceState) {
    ...
    String[] args = getArgsFromIntent(this.activity.getIntent());
    FlutterMain.ensureInitializationComplete(this.activity.getApplicationContext(), args);
    this.flutterView = this.viewFactory.createFlutterView(this.activity);
    if (this.flutterView == null) {
        FlutterNativeView nativeView = this.viewFactory.createFlutterNativeView();
        this.flutterView = new FlutterView(this.activity, (AttributeSet)null, nativeView);
        this.flutterView.setLayoutParams(matchParent);
        this.activity.setContentView(this.flutterView);
        this.launchView = this.createLaunchView();
        if (this.launchView != null) {
            this.addLaunchView();
        }
    }
   ...
   this.runBundle(appBundlePath);
   ... 
}

在这里我们需要注意FlutterMain.ensureInitializationComplete的执行,

//FlutterMain.java

public static void ensureInitializationComplete(Context applicationContext, String[] args) {
    ...
    sResourceExtractor.waitForCompletion();
    ...
    nativeInit(applicationContext, (String[])shellArgs.toArray(new String[0]), appBundlePath, appStoragePath, engineCachesPath);
    sInitialized = true;
    ...
}

//c++关键方法1
private static native void nativeInit(Context var0, String[] var1, String var2, String var3, String var4);

它将等待解压任务结束,资源处理完毕,然后拼接参数,完成参数初始化后将执行nativeInit方法对c++层初始化。

然后会创建FlutterView对象,这里面还包含了很多关键对象的创建,这个下文将会分析到。

//FlutterView.java的构造方法
public FlutterView(Context context, AttributeSet attrs, FlutterNativeView nativeView) {
    super(context, attrs);
    ...
    if (nativeView == null) {
        this.mNativeView = new FlutterNativeView(activity.getApplicationContext());
    } else {
        this.mNativeView = nativeView;
    }
    this.mNativeView.getFlutterJNI();
    this.mIsSoftwareRenderingEnabled = FlutterJNI.nativeGetIsSoftwareRenderingEnabled();
    ...
  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值