热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

FlutterAndroid启动源码分析(一)

前言版本:Flutter1.20.4stable这个系列主要讲解在Flutter的项目中,Android从启动到加载Flutter等一系列的


前言

版本:Flutter 1.20.4 stable

这个系列主要讲解在Flutter的项目中,Android 从启动到加载Flutter等一系列的过程。

本文主要是对FlutterApplication的startInitialization方法及FlutterActivity整个类源码的分析


Application

android:name="io.flutter.app.FlutterApplication"
android:label="flutter_channel"
android:icon="@mipmap/ic_launcher">

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

在Android项目的AndroidManifest.xml中指定了application为FlutterApplication,主要是一个初始化操作

最终会调用FlutterLoader类中的startInitialization方法

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");
}
applicationContext = applicationContext.getApplicationContext();
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);
}

  • 加载Flutter引擎的本机库以启用后续的JNI调用
  • 开始定位和打开应用程序APK中打包的Dart资源

FlutterApplication不 做过多分析,就是一些资源的初始化和so库加载的一些操作


FlutterActivity

class MainActivity : FlutterActivity(){}

public class FlutterActivity extends Activity
implements FlutterActivityAndFragmentDelegate.Host, LifecycleOwner {

public FlutterActivity() {
lifecycle = new LifecycleRegistry(this);
}

它是继承Activity并实现了FlutterActivityAndFragmentDelegate这个代理类中的Host接口及获取生命周期的LifecycleOwner接口

构造函数里实例化了一个LifecycleRegistry,它继承Lifecycle

public class LifecycleRegistry extends Lifecycle

然后实现LifecycleOwner接口的getLifecycle方法,返回了LifecycleRegistry对象,用于生命周期状态的监听和通知,这个不用过多介绍

@Override
@NonNull
public Lifecycle getLifecycle() {
return lifecycle;
}



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();
}

@NonNull
private View createFlutterView() {
return delegate.onCreateView(
null /* inflater */, null /* container */, null /* savedInstanceState */);
}

对于主题和状态栏的设置我们不去关注,重点看一下configureWindowForTransparency这个方法和对FlutterActivityAndFragmentDelegate的一些操作


configureWindowForTransparency

如果FlutterActivity背景模式是透明(默认是不透明的模式),则设置整个FlutterActivity窗口透明及隐藏状态栏

其实如果我们不在原生项目中使用FlutterModule进行混合开发的话,是不需要关注这个方法的。因为默认就是非透明模式。

这里只是先提一嘴,后续讲到混合开发时会涉及到这个方法的一些配置

private void configureWindowForTransparency() {
BackgroundMode backgroundMode = getBackgroundMode();
if (backgroundMode == BackgroundMode.transparent) {
getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
}

FlutterActivityAndFragmentDelegate


  1. 主要是实例化了FlutterActivityAndFragmentDelegate,传递FlutterActivityAndFragmentDelegate.Host实现类即当前类this
  2. 调用delegate.onAttach、onActivityCreated及onCreateView方法
  3. 关于FlutterActivityAndFragmentDelegate的介绍,我们放到下一篇文章里



其他生命周期方法大同小异,基本都是通过LifecycleRegistry.handleLifecycleEvent设置当前界面状态。然后将当前生命周期委托给delegate进行操作

@Override
protected void onStart() {
super.onStart();
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START);
delegate.onStart();
}
@Override
protected void onResume() {
super.onResume();
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
delegate.onResume();
}
@Override
public void onPostResume() {
super.onPostResume();
delegate.onPostResume();
}
@Override
protected void onPause() {
super.onPause();
delegate.onPause();
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
}



接下来就是一些重写FlutterActivityAndFragmentDelegate.Host接口的方法

/* package */ interface Host
extends SplashScreenProvider, FlutterEngineProvider, FlutterEngineConfigurator {

我们先看一下这个Host接口具体有哪些方法

下面根据其用途进行了一个大致的分类


  • 获取Context、Activity、Lifecycle


    方法名描述
    Context getContext();获取上下文对象
    Activity getActivity();获取activity对象
    Lifecycle getLifecycle();获取Lifecycle,返回的就是上面说的LifecycleRegistry
  • 实例化FlutterEngine


    方法名描述
    String getCachedEngineId();缓存的FlutterEngine Id
    FlutterEngine provideFlutterEngine(@NonNull Context context);提供一个FlutterEngine,目前版本返回null,暂不考虑
    FlutterShellArgs getFlutterShellArgs();初始化参数
    boolean shouldAttachEngineToActivity();建立Engine和Activity的连接关系,控制界面用于向附加到 FlutterEngine的插件提供Android资源和生命周期事件。
    PlatformPlugin providePlatformPlugin( @Nullable Activity activity, @NonNull FlutterEngine flutterEngine);提供一个PlatformPlugin(Android平台的插件实现)
  • 在FlutterView里首次运行Dart所需参数


    方法名描述
    String getAppBundlePath();返回包含dart代码的app bundle 路径
    String getInitialRoute();初始化路由路径
    String getDartEntrypointFunctionName();dart代码执行入口函数名称
  • 实例化FlutterSplashView(启动界面及整个FlutterView)


    方法名描述
    RenderMode getRenderMode();Flutter UI 渲染模式,默认是surface
    TransparencyMode getTransparencyMode();透明度模式,默认是opaque
    void onFlutterSurfaceViewCreated(@NonNull FlutterSurfaceView flutterSurfaceView);FlutterSurfaceView创建回调
    void onFlutterTextureViewCreated(@NonNull FlutterTextureView flutterTextureView);FlutterTextureView创建回调
    void onFlutterUiDisplayed();FlutterView首次渲染回调
    void onFlutterUiNoLongerDisplayed();FlutterView停止渲染回调
    SplashScreen provideSplashScreen();返回一个SplashScreen

    方法名描述
    boolean shouldDestroyEngineWithHost();是否清理engine

这里我们只对configureFlutterEngine方法实现做详细分析,剩余的在下篇文章中具体说明


configureFlutterEngine 插件注册方法

在FlutterActivityAndFragmentDelegate.onAttach方法中进行调用

void onAttach(@NonNull Context context) {
// 省略部分代码
host.configureFlutterEngine(flutterEngine);
}

FlutterActivity对其实现如下

@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
registerPlugins(flutterEngine);
}
private static void registerPlugins(@NonNull FlutterEngine flutterEngine) {
try {
Class generatedPluginRegistrant =
Class.forName("io.flutter.plugins.GeneratedPluginRegistrant");
Method registrationMethod =
generatedPluginRegistrant.getDeclaredMethod("registerWith", FlutterEngine.class);
registrationMethod.invoke(null, flutterEngine);
} catch (Exception e) {
Log.w(
TAG,
"Tried to automatically register plugins with FlutterEngine ("
+ flutterEngine
+ ") but could not find and invoke the GeneratedPluginRegistrant.");
}
}

这里通过反射执行GeneratedPluginRegistrant.registerWith方法来注册pubspec.yaml中添加的插件依赖

@Keep
public final class GeneratedPluginRegistrant {
public static void registerWith(@NonNull FlutterEngine flutterEngine) {
flutterEngine.getPlugins().add(new com.befovy.fijkplayer.FijkPlugin());
}
}

registerWith方法中的 flutterEngine.getPlugins().add(xxx)无需我们手动添加,当执行pub get 时,如果含原生插件,则flutter会自动去添加,而且其实如果我们不注册自己的原生插件的话,这个方法其实也是不需要去做任何操作的。默认都是自动注册。这个方法及其业务逻辑在最近Flutter几个版本的更新中有很大的变化

如果我们要注册自己的原生插件,则需要在MainActivity中重写configureFlutterEngine并调用super.configureFlutterEngine,然后通过 flutterEngine.plugins.add方法进行注册

class MainActivity : FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
// 原生封装的FlutterPlugin需要手动进行注册
flutterEngine.plugins.add(ToastPlugin())
}
}

总结

通过本文我们可以学习到


  1. FlutterApplication主要做了哪些工作
  2. MainActivity继承的FlutterActivity主要做了哪些工作

以上内容如有不准确的地方,麻烦大家在评论区指出,我会一一改正

下篇文章会分析FlutterActivityAndFragmentDelegate这个代理类的一些逻辑,这个类比较关键,它是主要负责FlutterActivity和FlutterEngine、FlutterView、PlatformPlugin等一些联动工作,比如Engine注册、Dart执行、平台插件实现以及Activity和Engine生命周期的一些控制等等,同时会衍生出很多类。可以说这篇文章只是一个起点,核心业务在后面。


本文地址:https://blog.csdn.net/fighting_android/article/details/108700276



推荐阅读
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • Spring学习(4):Spring管理对象之间的关联关系
    本文是关于Spring学习的第四篇文章,讲述了Spring框架中管理对象之间的关联关系。文章介绍了MessageService类和MessagePrinter类的实现,并解释了它们之间的关联关系。通过学习本文,读者可以了解Spring框架中对象之间的关联关系的概念和实现方式。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文讨论了在Spring 3.1中,数据源未能自动连接到@Configuration类的错误原因,并提供了解决方法。作者发现了错误的原因,并在代码中手动定义了PersistenceAnnotationBeanPostProcessor。作者删除了该定义后,问题得到解决。此外,作者还指出了默认的PersistenceAnnotationBeanPostProcessor的注册方式,并提供了自定义该bean定义的方法。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
author-avatar
S_o_m_n_u_211
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有