8

前言

回想在公司工作拿到的第一个项目是一个flash游戏项目,在那个时候flash游戏非常流行,还没有被html5取代的迹象。游戏程序架构采用的是后端mfc+前端flash框架,整个项目代码20万行,就我自己一个人开发。公司的要求是能修改、增加游戏的功能。当时我虽然有一点mfc的基础,但是游戏没有接触过、flash的actionscript3更是一窍不通。那怎么办呢?学呗。于是经过一两个月的各种画uml图、流程图、写伪代码等等一系列的理解学习,发现不但理解了后端、前端的工作原理,甚至可以开始撸框架了。那个时候成天跟人吹牛,现在想起来还是觉得十分的有趣。一个看似庞大的体系从一窍不通到彻底掌握,这个过程只要经历一遍,之后就觉得没有什么问题是解决不了的。

flutter在实现上破天荒的没有采用目前的各种成熟视图体系,而是采用了自己构建一套视图体系,用gpu加速,所以性能高、界面流畅。对此,表示十分的感兴趣。那么要彻底的挖掘一个框架的本质,就只有研究源码这么一条道路。从今天起,预计花一到两个月的时间来分析flutter的源码,在这里给大家分享下研究的过程。

这一系列的文章应该会非常长,研究源码需要耐心,不是么。

文章结构

笔者认为这样

  • 分析代码
  • 提出这段代码问题,应该在后续的分析中解决
  • 解决问题,分析前面的问题哪些是解决的
  • 总结代码
  • 在阶段性分析后给出图

flutter源码分析之FlutterActivity

实现接口分析


/// activity实现了三个接口
public class FlutterActivity extends Activity implements Provider, PluginRegistry, ViewFactory {

/// 视图提供类,一个方法getFlutterView
public interface Provider {
    FlutterView getFlutterView();
}

/// 插件注册
public interface PluginRegistry {
    /// 注册一个插件
    PluginRegistry.Registrar registrarFor(String var1);
    /// 是否有这个插件
    boolean hasPlugin(String var1);
    /// 插件发布值
    <T> T valuePublishedByPlugin(String var1);
    /// 下面开始为插件生命周期回调
    public interface PluginRegistrantCallback {
        void registerWith(PluginRegistry var1);
    }

    /// 显然是视图销毁的回调
    public interface ViewDestroyListener {
        boolean onViewDestroy(FlutterNativeView var1);
    }
        
    //// 不知道干啥,先留着
    public interface UserLeaveHintListener {
        void onUserLeaveHint();
    }
   
    //// activity生命周期回调之onNewIntent
    public interface NewIntentListener {
        boolean onNewIntent(Intent var1);
    }
    
  //// activity生命周期回调之onActivityResult
    public interface ActivityResultListener {
        boolean onActivityResult(int var1, int var2, Intent var3);
    }

//// activity生命周期回调之onRequestPermissionsResult
    public interface RequestPermissionsResultListener {
        boolean onRequestPermissionsResult(int var1, String[] var2, int[] var3);
    }
    /// 插件的注册者,相当于插件的宿主。
    public interface Registrar {
        Activity activity();

        Context context();

        Context activeContext();
        /// 这个BinaryMessager还不知道干啥
        BinaryMessenger messenger();
        /// TextureRegistry不清楚
        TextureRegistry textures();
        /// 获取视图
        FlutterView view();
        /// 寻找资源
        String lookupKeyForAsset(String var1);
        /// 寻找资源
        String lookupKeyForAsset(String var1, String var2);
        /// 发布值,与上面的valuePublishedByPlugin对应
        PluginRegistry.Registrar publish(Object var1);
        
        /// 增加生命周期回调
        PluginRegistry.Registrar addRequestPermissionsResultListener(PluginRegistry.RequestPermissionsResultListener var1);

        /// 增加生命周期回调
        PluginRegistry.Registrar addActivityResultListener(PluginRegistry.ActivityResultListener var1);

        PluginRegistry.Registrar addNewIntentListener(PluginRegistry.NewIntentListener var1);

        /// 增加生命周期回调
        PluginRegistry.Registrar addUserLeaveHintListener(PluginRegistry.UserLeaveHintListener var1);
        
        /// 增加生命周期回调
        PluginRegistry.Registrar addViewDestroyListener(PluginRegistry.ViewDestroyListener var1);
    }
}

/// 视图工厂
  public interface ViewFactory {
        /// 创建flutterView
        FlutterView createFlutterView(Context var1);
        //// 创建nativeview
        FlutterNativeView createFlutterNativeView();
        ///  暂时搞不清楚干啥的,先留着
        boolean retainFlutterNativeView();
    }

问题

  • (1)FlutterNativeView和FlutterView有啥区别和联系
  • (2)UserLeaveHintListener作用?
  • (3)ViewFactory#retainFlutterNativeView作用?
  • (4)BinaryMessenger作用
  • (5)TextureRegistry作用

这些问题在之后的分析中应该能解决。

Activity的生命周期分析

构造函数


///创建FlutterActivityDelegate
 private final FlutterActivityDelegate delegate = new FlutterActivityDelegate(this, this);
    private final FlutterActivityEvents eventDelegate;
    private final Provider viewProvider;
    private final PluginRegistry pluginRegistry;

    public FlutterActivity() {
    /// FlutterActivityDelegate实现了这三个接口,并赋值给三个变量,这样调用起来更加清晰。
        this.eventDelegate = this.delegate;
        this.viewProvider = this.delegate;
        this.pluginRegistry = this.delegate;
    }

onCreate、onResume、onStop、onDestory、onPause、onNewIntent、onStart、onActivityResult、onRequestPermissionResult

///这里都是由创建FlutterActivityDelegate代理执行,就不一一贴出来了
protected void onXXX() {
        super.onXXX();
        this.eventDelegate.onXXX();
    }

创建FlutterView

值得注意的是这里的三个回调,表示FlutterView是如何创建出来的。

  public FlutterView getFlutterView() {
  /// 有关的函数,只有这个由FlutterActivityDelegate代理执行
        return this.viewProvider.getFlutterView();
    }

    public FlutterView createFlutterView(Context context) {
        return null;
    }

    public FlutterNativeView createFlutterNativeView() {
        return null;
    }

    public boolean retainFlutterNativeView() {
        return false;
    }

FlutterActivity总结

  • FlutterActivity的生命周期和各个方法实际上由FlutterActivityDelegate代理执行。
  • 从Activity的源码来看,已经清晰的看出FlutterActivity解决了生命周期的回调,插件管理,创建FlutterView以及相关的ui。

问题

  • (6)FlutterView究竟如何创建的
  • (7)retainFlutterNativeView有什么作用

flutter源码分析之FlutterActivityDelegate

还是onCreate


/// 启动参数解析
String[] args = getArgsFromIntent(this.activity.getIntent());
/// 等待并保证初始化完成
FlutterMain.ensureInitializationComplete(this.activity.getApplicationContext(), args);
/// 创建flutterView,注意到上面默认的返回null
        this.flutterView = this.viewFactory.createFlutterView(this.activity);
        if (this.flutterView == null) {
        /// 默认走这里,createFlutterNativeView默认返回null
            FlutterNativeView nativeView = this.viewFactory.createFlutterNativeView();
            //实际创建了FlutterView
            this.flutterView = new FlutterView(this.activity, (AttributeSet)null, nativeView);
            // 设置layout,并添加到当前activity,作为主视图
            this.flutterView.setLayoutParams(matchParent);
            this.activity.setContentView(this.flutterView);
            //创建启动ui
            this.launchView = this.createLaunchView();
            if (this.launchView != null) {
               //如果有创建启动ui成功,那么增加到当前activity上面
                this.addLaunchView();
            }
        }

看下FlutterMain.ensureInitializationComplete

 public static void ensureInitializationComplete(Context applicationContext, String[] args) {
         // 保证ui线程运行
        if (Looper.myLooper() != Looper.getMainLooper()) {
            throw new IllegalStateException("ensureInitializationComplete must be called on the main thread");
        } else if (!sInitialized) {
            try {
               // 等待完成,这里有个疑问点,sResourceExtractor是什么时候创建的
                sResourceExtractor.waitForCompletion();
                
                // 继续解析参数
                List<String> shellArgs = new ArrayList();
                shellArgs.add("--icu-data-file-path=" + new File(PathUtils.getDataDirectory(applicationContext), "icudtl.dat"));
                if (args != null) {
                    Collections.addAll(shellArgs, args);
                }

                if (sIsPrecompiledAsSharedLibrary) {
                    shellArgs.add("--aot-shared-library-path=" + new File(PathUtils.getDataDirectory(applicationContext), sAotSharedLibraryPath));
                } else {
                    if (sIsPrecompiledAsBlobs) {
                        shellArgs.add("--aot-snapshot-path=" + PathUtils.getDataDirectory(applicationContext));
                    } else {
                        shellArgs.add("--cache-dir-path=" + PathUtils.getCacheDirectory(applicationContext));
                        shellArgs.add("--aot-snapshot-path=" + PathUtils.getDataDirectory(applicationContext) + "/" + sFlutterAssetsDir);
                    }

                    shellArgs.add("--vm-snapshot-data=" + sAotVmSnapshotData);
                    shellArgs.add("--vm-snapshot-instr=" + sAotVmSnapshotInstr);
                    shellArgs.add("--isolate-snapshot-data=" + sAotIsolateSnapshotData);
                    shellArgs.add("--isolate-snapshot-instr=" + sAotIsolateSnapshotInstr);
                }

                if (sSettings.getLogTag() != null) {
                    shellArgs.add("--log-tag=" + sSettings.getLogTag());
                }
                
                // 查找bundle
                String appBundlePath = findAppBundlePath(applicationContext);
                // native初始化,参数为解析的所有启动参数和一个bundle的路径
                nativeInit(applicationContext, (String[])shellArgs.toArray(new String[0]), appBundlePath);
                sInitialized = true;
            } catch (Exception var4) {
                Log.e("FlutterMain", "Flutter initialization failed.", var4);
                throw new RuntimeException(var4);
            }
        }
    }
  ///这里的nativeInit是jni调用,实际作用是? 这里我猜是初始化dart环境,并初始化加载bundle,类似初始化js环境,并加载jsbundle
  private static native void nativeInit(Context var0, String[] var1, String var2);

看下:

  sResourceExtractor.waitForCompletion();

sResourceExtractor是啥时候创建的?那么这里全局搜索了一番,了解到到FlutterMain#startInitialization这个方法是在FlutterApplication中调用的,所以先看下Application。这里先提出疑问,之后解决。

问题

  • (8)sResourceExtractor.waitForCompletion();在干什么?
  • (9)new FlutterView(this.activity, (AttributeSet)null, nativeView);这里是否可以解释前面的问题(1)
  • (10) nativeInit作用?bundle是什么,如何加载?

flutter源码分析之FlutterApplication

本来这个Application应该是第一个分析的,但是首先用户看到的flutter创建的example里面暴露的第一个类应该就是FlutterActivity。FlutterApplication是在AndroidManifest中定义的,所以笔者一开始没有注意到,这里插个队补上。


public class FlutterApplication extends Application {
    private Activity mCurrentActivity = null;

    public FlutterApplication() {
    }

    // 显然这里进行了全局初始化
    @CallSuper
    public void onCreate() {
        super.onCreate();
        FlutterMain.startInitialization(this);
    }

    public Activity getCurrentActivity() {
        return this.mCurrentActivity;
    }
    
    // 设置当前的Activity
    public void setCurrentActivity(Activity mCurrentActivity) {
        this.mCurrentActivity = mCurrentActivity;
    }
}

FlutterMain.startInitialization

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");
            long initTimeMillis = SystemClock.uptimeMillis() - initStartTimestampMillis;
            nativeRecordStartTimestamp(initTimeMillis);
        }
    }

Setting

这里的Setting非常简单,只是提供了日志的tag,那么这个logTag在哪里用?又是一个疑问。

public static class Settings {
        private String logTag;

        public Settings() {
        }

        public String getLogTag() {
            return this.logTag;
        }

        public void setLogTag(String tag) {
            this.logTag = tag;
        }
    }

initConfig

initConfig,这个函数主要用于初始化配置

 private static void initConfig(Context applicationContext) {
        try {
            Bundle metadata = applicationContext.getPackageManager().getApplicationInfo(applicationContext.getPackageName(), 128).metaData;
            if (metadata != null) {
                sAotSharedLibraryPath = metadata.getString(PUBLIC_AOT_AOT_SHARED_LIBRARY_PATH, "app.so");
                sAotVmSnapshotData = metadata.getString(PUBLIC_AOT_VM_SNAPSHOT_DATA_KEY, "vm_snapshot_data");
                sAotVmSnapshotInstr = metadata.getString(PUBLIC_AOT_VM_SNAPSHOT_INSTR_KEY, "vm_snapshot_instr");
                sAotIsolateSnapshotData = metadata.getString(PUBLIC_AOT_ISOLATE_SNAPSHOT_DATA_KEY, "isolate_snapshot_data");
                sAotIsolateSnapshotInstr = metadata.getString(PUBLIC_AOT_ISOLATE_SNAPSHOT_INSTR_KEY, "isolate_snapshot_instr");
                sFlx = metadata.getString(PUBLIC_FLX_KEY, "app.flx");
                sSnapshotBlob = metadata.getString(PUBLIC_SNAPSHOT_BLOB_KEY, "snapshot_blob.bin");
                sFlutterAssetsDir = metadata.getString(PUBLIC_FLUTTER_ASSETS_DIR_KEY, "flutter_assets");
            }

        } catch (NameNotFoundException var2) {
            throw new RuntimeException(var2);
        }
    }

这里可以看到flutter的定制选项,可以在androd的meta里面定义

  • sAotSharedLibraryPath
  • sAotVmSnapshotData
  • sAotVmSnapshotInstr
  • sAotIsolateSnapshotData
  • sAotIsolateSnapshotInstr
  • sFlx
  • sSnapshotBlob
  • sFlutterAssetsDir

initAot

关于aot,这里有几篇博文介绍:
https://www.cnblogs.com/zengm...
https://www.cnblogs.com/tinyt...

AOT是一种静态编译技术,与JIT对应

private static void initAot(Context applicationContext) {
        // 列出所有的assets文件夹中的资源
        Set<String> assets = listRootAssets(applicationContext);
        // 
        sIsPrecompiledAsBlobs = assets.containsAll(Arrays.asList(sAotVmSnapshotData, sAotVmSnapshotInstr, sAotIsolateSnapshotData, sAotIsolateSnapshotInstr));
        sIsPrecompiledAsSharedLibrary = assets.contains(sAotSharedLibraryPath);
        // 意思是两个不能同时存在?
        if (sIsPrecompiledAsBlobs && sIsPrecompiledAsSharedLibrary) {
            throw new RuntimeException("Found precompiled app as shared library and as Dart VM snapshots.");
        }
    }

initResources

 private static void initResources(Context applicationContext) {
         // 开始清理资源
        (new ResourceCleaner(applicationContext)).start();
        
        // 创建sResourceExtractor
        sResourceExtractor = (new ResourceExtractor(applicationContext)).addResources(SKY_RESOURCES).addResource(fromFlutterAssets(sFlx)).addResource(fromFlutterAssets(sSnapshotBlob)).addResource(fromFlutterAssets(sAotVmSnapshotData)).addResource(fromFlutterAssets(sAotVmSnapshotInstr)).addResource(fromFlutterAssets(sAotIsolateSnapshotData)).addResource(fromFlutterAssets(sAotIsolateSnapshotInstr)).addResource(fromFlutterAssets("kernel_blob.bin")).addResource(fromFlutterAssets("platform.dill"));
        
        // 增加资源
        if (sIsPrecompiledAsSharedLibrary) {
            sResourceExtractor.addResource(sAotSharedLibraryPath);
        } else {
            sResourceExtractor.addResource(sAotVmSnapshotData).addResource(sAotVmSnapshotInstr).addResource(sAotIsolateSnapshotData).addResource(sAotIsolateSnapshotInstr).addResource(sSnapshotBlob);
        }
        //开始
        sResourceExtractor.start();
    }

看下:
(new ResourceCleaner(applicationContext)).start(),作用是清理缓存

  boolean result = name.startsWith(".org.chromium.Chromium.");
                    return result;
 ...
  protected Void doInBackground(Void... unused) {
              File[] var2 = this.mFilesToDelete;
            int var3 = var2.length;

            for(int var4 = 0; var4 < var3; ++var4) {
                File file = var2[var4];
                if (file.exists()) {
                    this.deleteRecursively(file);
                }
            }
}

看下:sResourceExtractor.start();

 ResourceExtractor start() {
        assert this.mExtractTask == null;

        this.mExtractTask = new ResourceExtractor.ExtractTask();
        this.mExtractTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new Void[0]);
        return this;
    }
...
 private void extractResources() {
  File dataDir = new File(PathUtils.getDataDirectory(ResourceExtractor.this.mContext));
 ...
 InputStream is = manager.open(asset);
 Throwable var9 = null;

try {
  OutputStream os = new FileOutputStream(output);
 Throwable var11 = null;
...
  while((count = is.read(buffer, 0, 16384)) != -1) {
       os.write(buffer, 0, count);
  }
...
}
...
public final class PathUtils {
    ...
    public static String getDataDirectory(Context applicationContext) {
        return applicationContext.getDir("Lflutter", 0).getPath();
    }
    ...
}

这段代码是将指定的assert文件夹中的文件拷贝到应用程序目录中的flutter文件夹下,说明后续程序需要直接使用文件,而不是assert文件夹中的二进制。

native部分

System.loadLibrary("flutter");
nativeRecordStartTimestamp(initTimeMillis);

初始化native,并记录时间,native的部分,这篇文章先不予考虑,专门在一个专题里面写。

问题

这次光看代码比较难以理解,需要动态调试了

  • (11)sIsPrecompiledAsBlobs && sIsPrecompiledAsSharedLibrary这两个参数具体代表什么含义,为什么不能同时存在?和flutter的hotload有关吗,和flutter是调试版本还是发布版本有关吗?
  • (12)flutter中的so库具体有哪些,有什么作用?

解决问题

  • (8)sResourceExtractor.waitForCompletion();在干什么?

这次显然已经解决了前面的问题(8), FlutterActivity在启动的时候,需要等待FlutterApplicaiton中的异步加载资源完毕

总结

FlutterApplication在onCreate的时候,初始化加载Flutter中的资源,含bundle、so库等重要启动资源,而在FlutterActivity的onCreate中,会等待FlutterApplication的这个过程完毕之后再进行下一步的初始化。

Flutter源码分析创建FlutterView

这里接着上面来分析FlutterView的创建过程:

public class FlutterView extends SurfaceView implements BinaryMessenger, TextureRegistry, AccessibilityStateChangeListener {

注意到FlutterView继承了SurfaceView,关于SurfaceView,可以参考几篇博文理解:

https://blog.csdn.net/android...
https://www.cnblogs.com/zhang...

SurfaceView使用的绘图线程不是ui线程,我们平时使用的摄像头、游戏之类的要求图形性能比较高的场景就靠它了。

看下构造函数:

this.nextTextureId = new AtomicLong(0L);
...
@Override
    public TextureRegistry.SurfaceTextureEntry createSurfaceTexture() {
        final SurfaceTexture surfaceTexture = new SurfaceTexture(0);
        surfaceTexture.detachFromGLContext();
        final SurfaceTextureRegistryEntry entry =
                new SurfaceTextureRegistryEntry(nextTextureId.getAndIncrement(), surfaceTexture);
        nativeRegisterTexture(mNativeView.get(), entry.id(), surfaceTexture);
        return entry;
    }

这里使用到了SurfaceTexture,并执行了nativeRegisterTexture,关于SurfaceTexture,找到这么几篇博文:

https://www.cnblogs.com/wytig...
https://blog.csdn.net/hejjunl...
https://blog.csdn.net/u010949...
https://blog.csdn.net/tq08g2z...
https://blog.csdn.net/OnafioO...
https://blog.csdn.net/u010949...
https://blog.csdn.net/u010949...

基本上全是csdn的老文章!

这个SurfactTexture具体作用?先放放。

接着往下看:

this.mIsSoftwareRenderingEnabled = nativeGetIsSoftwareRenderingEnabled();

关于android的软件渲染还是硬件渲染:
https://blog.csdn.net/wlwl007...
https://blog.csdn.net/luoshen...
http://www.sohu.com/a/1605251...

继续

this.mMetrics = new FlutterView.ViewportMetrics();
this.mMetrics.devicePixelRatio = context.getResources().getDisplayMetrics().density;
...
 private void updateViewportMetrics() {
        if (this.isAttached()) {
            nativeSetViewportMetrics(this.mNativeView.get(), this.mMetrics.devicePixelRatio, this.mMetrics.physicalWidth, this.mMetrics.physicalHeight, this.mMetrics.physicalPaddingTop, this.mMetrics.physicalPaddingRight, this.mMetrics.physicalPaddingBottom, this.mMetrics.physicalPaddingLeft, this.mMetrics.physicalViewInsetTop, this.mMetrics.physicalViewInsetRight, this.mMetrics.physicalViewInsetBottom, this.mMetrics.physicalViewInsetLeft);
            WindowManager wm = (WindowManager)this.getContext().getSystemService("window");
            float fps = wm.getDefaultDisplay().getRefreshRate();
            VsyncWaiter.refreshPeriodNanos = (long)(1.0E9D / (double)fps);
        }
    }
...
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
        this.mMetrics.physicalWidth = width;
        this.mMetrics.physicalHeight = height;
        this.updateViewportMetrics();
        super.onSizeChanged(width, height, oldWidth, oldHeight);
    }

    public final WindowInsets onApplyWindowInsets(WindowInsets insets) {
        this.mMetrics.physicalPaddingTop = insets.getSystemWindowInsetTop();
        this.mMetrics.physicalPaddingRight = insets.getSystemWindowInsetRight();
        this.mMetrics.physicalPaddingBottom = 0;
        this.mMetrics.physicalPaddingLeft = insets.getSystemWindowInsetLeft();
        this.mMetrics.physicalViewInsetTop = 0;
        this.mMetrics.physicalViewInsetRight = 0;
        this.mMetrics.physicalViewInsetBottom = insets.getSystemWindowInsetBottom();
        this.mMetrics.physicalViewInsetLeft = 0;
        this.updateViewportMetrics();
        return super.onApplyWindowInsets(insets);
    }

    protected boolean fitSystemWindows(Rect insets) {
        if (VERSION.SDK_INT <= 19) {
            this.mMetrics.physicalPaddingTop = insets.top;
            this.mMetrics.physicalPaddingRight = insets.right;
            this.mMetrics.physicalPaddingBottom = 0;
            this.mMetrics.physicalPaddingLeft = insets.left;
            this.mMetrics.physicalViewInsetTop = 0;
            this.mMetrics.physicalViewInsetRight = 0;
            this.mMetrics.physicalViewInsetBottom = insets.bottom;
            this.mMetrics.physicalViewInsetLeft = 0;
            this.updateViewportMetrics();
            return true;
        } else {
            return super.fitSystemWindows(insets);
        }
    }

    private boolean isAttached() {
        return this.mNativeView != null && this.mNativeView.isAttached();
    }

这里又涉及到几个概念,基本都不怎么常用:
WindowInsets,onApplyWindowInsets:
https://blog.csdn.net/me_touc...
fitSystemWindows:
https://blog.csdn.net/ys40897...

static final class ViewportMetrics {
        float devicePixelRatio = 1.0F;
        int physicalWidth = 0;
        int physicalHeight = 0;
        int physicalPaddingTop = 0;
        int physicalPaddingRight = 0;
        int physicalPaddingBottom = 0;
        int physicalPaddingLeft = 0;
        int physicalViewInsetTop = 0;
        int physicalViewInsetRight = 0;
        int physicalViewInsetBottom = 0;
        int physicalViewInsetLeft = 0;

        ViewportMetrics() {
        }
    }

这段代码的意思显然是适配窗口大小的变化,并在恰当的时候更新mMetrics,并设置到native中

 private static native void nativeSetViewportMetrics(long nativePlatformViewAndroid,
            float devicePixelRatio, int physicalWidth, int physicalHeight, int physicalPaddingTop,
            int physicalPaddingRight, int physicalPaddingBottom, int physicalPaddingLeft,
            int physicalViewInsetTop, int physicalViewInsetRight, int physicalViewInsetBottom,
            int physicalViewInsetLeft);

继续:

         Activity activity = (Activity)this.getContext();
        if (nativeView == null) {
            this.mNativeView = new FlutterNativeView(activity.getApplicationContext());
        } else {
            this.mNativeView = nativeView;
        }

NativeView是什么?

public class FlutterNativeView implements BinaryMessenger {
...
public FlutterNativeView(Context context) {
        this.mContext = context;
        // 插件管理
        this.mPluginRegistry = new FlutterPluginRegistry(this, context);
        this.attach(this);
        this.assertAttached();
        // 消息管理
        this.mMessageHandlers = new HashMap();
    }
...
    //涉及到和native打交道
private static native long nativeAttach(FlutterNativeView var0);

    private static native void nativeDestroy(long var0);

    private static native void nativeDetach(long var0);

    private static native void nativeRunBundleAndSnapshot(long var0, String var2, String var3, String var4, boolean var5, AssetManager var6);

    private static native void nativeRunBundleAndSource(long var0, String var2, String var3, String var4);

    private static native void nativeSetAssetBundlePathOnUI(long var0, String var2);

    private static native String nativeGetObservatoryUri();

    private static native void nativeDispatchEmptyPlatformMessage(long var0, String var2, int var3);

    private static native void nativeDispatchPlatformMessage(long var0, String var2, ByteBuffer var3, int var4, int var5);

    private static native void nativeInvokePlatformMessageEmptyResponseCallback(long var0, int var2);

    private static native void nativeInvokePlatformMessageResponseCallback(long var0, int var2, ByteBuffer var3, int var4);
}

NativeView显然是一个插件、消息的管理类,并与native打交道,那么和FlutterView的关系,显然一个负责展示,一个负责交互。这里解决了问题(1)

再往下看

 this.mSurfaceCallback = new Callback() {
            public void surfaceCreated(SurfaceHolder holder) {
                FlutterView.this.assertAttached();
                FlutterView.nativeSurfaceCreated(FlutterView.this.mNativeView.get(), holder.getSurface(), color);
            }

            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                FlutterView.this.assertAttached();
                FlutterView.nativeSurfaceChanged(FlutterView.this.mNativeView.get(), width, height);
            }

            public void surfaceDestroyed(SurfaceHolder holder) {
                FlutterView.this.assertAttached();
                FlutterView.nativeSurfaceDestroyed(FlutterView.this.mNativeView.get());
            }
        };
        this.getHolder().addCallback(this.mSurfaceCallback);

这里监听了SurfaceView的生命周期,并调用native

 this.mAccessibilityManager = (AccessibilityManager)this.getContext().getSystemService("accessibility");
        this.mActivityLifecycleListeners = new ArrayList();
        this.mFirstFrameListeners = new ArrayList();
        this.mFlutterLocalizationChannel = new MethodChannel(this, "flutter/localization", JSONMethodCodec.INSTANCE);
        this.mFlutterNavigationChannel = new MethodChannel(this, "flutter/navigation", JSONMethodCodec.INSTANCE);
        this.mFlutterKeyEventChannel = new BasicMessageChannel(this, "flutter/keyevent", JSONMessageCodec.INSTANCE);
        this.mFlutterLifecycleChannel = new BasicMessageChannel(this, "flutter/lifecycle", StringCodec.INSTANCE);
        this.mFlutterSystemChannel = new BasicMessageChannel(this, "flutter/system", JSONMessageCodec.INSTANCE);
        this.mFlutterSettingsChannel = new BasicMessageChannel(this, "flutter/settings", JSONMessageCodec.INSTANCE);
        PlatformPlugin platformPlugin = new PlatformPlugin(activity);
        MethodChannel flutterPlatformChannel = new MethodChannel(this, "flutter/platform", JSONMethodCodec.INSTANCE);
        flutterPlatformChannel.setMethodCallHandler(platformPlugin);
        this.addActivityLifecycleListener(platformPlugin);
        this.mImm = (InputMethodManager)this.getContext().getSystemService("input_method");
        this.mTextInputPlugin = new TextInputPlugin(this);
        this.setLocale(this.getResources().getConfiguration().locale);
        this.setUserSettings();

这段代码注册了一些Flutter的自带插件,主要用于输入、生命周期、国际化等系统相关的插件,有时间再一个一个分析,先放放。

问题

  • (13)native中的初始化流程?
  • (14)这里并没有看到一行代码有和绘制图形有关,那么在哪里调用?是否都是在native中调用,怎么调用的?

解决问题

  • (1)FlutterNativeView和FlutterView有啥区别和联系

本篇总结

全部问题:

  • (1)FlutterNativeView和FlutterView有啥区别和联系
  • (2)UserLeaveHintListener作用?
  • (3)ViewFactory#retainFlutterNativeView作用?
  • (4)BinaryMessenger作用
  • (5)TextureRegistry作用
  • (6)FlutterView究竟如何创建的
  • (7)retainFlutterNativeView有什么作用
  • (8)sResourceExtractor.waitForCompletion();在干什么?
  • (9)new FlutterView(this.activity, (AttributeSet)null, nativeView);这里是否可以解释前面的问题(1)
  • (10) nativeInit作用?bundle是什么,如何加载?
  • (11)sIsPrecompiledAsBlobs && sIsPrecompiledAsSharedLibrary这两个参数具体代表什么含义,为什么不能同时存在?和flutter的hotload有关吗,和flutter是调试版本还是发布版本有关吗?
  • (12)flutter中的so库具体有哪些,有什么作用?
  • (13)native中的初始化流程?
  • (14)这里并没有看到一行代码有和绘制图形有关,那么在哪里调用?是否都是在native中调用,怎么调用的?

大部分问题在这里都解释不了,这里先用一张图表示一下启动流程:

clipboard.png

如有疑问,请加qq群854192563讨论


jzoom
1.2k 声望334 粉丝

A simple way to solving problems is using tools like docker/Spring boot/React Native/React/Vue… Technology should not become a bottleneck in thinking.