重磅-Flutter 1.12正式版发布

前言

下午公众号给我推送了flutter 1.12正式版本发布的消息,官方声称这是flutter迄今为止最大的一次更新

  • 支持IOS 13暗黑模式
  • Flutter代码傻瓜式集成到原生项目-Add-to-App
  • N多widget的更新以及bug修复
  • Beta 版本的 web 支持以及 Alpha 版本的 macOS 支持

详情请参见:Flutter 1.12.13 release notes ,需要自己搭梯子

 

其中最让我痛心的莫过于Add-to-App功能,因为我特么上午才写了一篇关于flutter和native交互的博客,整整搞了两天!!!! 在我那篇博文中主要是集成了闲鱼的flutter-boost进行页面的跳转和数据交互。

为什么用flutter-boost?

  1. 可以共享FlutterEngine呀,为什么原生打开Flutter页面的一瞬间会出现白屏?因为FlutterEngine的初始化需要时间
  2. 数据交互easy得很,native-flutter, flutter-native, flutter-flutter,涵盖了我们能想到的各种姿势
  3. 这是在flutter 1.12版本之前最好的解决方案了,尽管有一些bug,但是闲鱼的大佬们都修复的差不多了

然而1.12版本的发布,我感觉flutter-boost这个库渐渐的可能就不会维护了,因为他有的功能官方基本上都支持了,而且花样更多,api更规范(除开数据交互,这一点我在官方文档上还没有看到介绍,不过这都是小case了,自己琢磨一下肯定有很不错的解决方案),下面让我们来解开Add-to-App的面纱

正文

这里我们只介绍android studio集成方式,因为这种方式最傻瓜易懂,而且今后肯定也是主流方案,想了解手动集成的同志请移步官方文档

开始之前先打个预防针,如果你的app支持x86架构,那还是放弃算了,因为flutter在release模式下只支持armeabi-v7a ,arm64-v8a 架构,所以在使用的时候记得在app的build.gradle中设置

android {
  //...
  defaultConfig {
    ndk {
      // Filter for architectures supported by Flutter.
      abiFilters 'armeabi-v7a', 'arm64-v8a'
    }
  }
}

吼吼吼,现在开始了。。。。。

1.在你的原生项目中使用File->New->New Module新建一个Flutter Module

然后填写module的信息

然后就ok啦!native项目会自动依赖新建的module,等build完成就可以直接运行了,是不是超级方便!!

 

添加Flutter页面

1.在AndroidManifest.xml中注册FlutterActivity

flutter提供了一个FlutterActivity来承载flutter页面,和其它activity一样,他也必须在manifest中注册

<activity
  android:name="io.flutter.embedding.android.FlutterActivity"
  android:theme="@style/LaunchTheme"
  android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
  android:hardwareAccelerated="true"
  android:windowSoftInputMode="adjustResize"
  />

@style/LaunchTheme可以被替换为任意的主题,所以根据你自己的需求修改即可。

 

2.启动FlutterActivity

当FlutterActivity在manifest中注册后,你可以在app的任意地方自动他,下面是一段启动FlutterActivity的代码

myButton.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View v) {
    startActivity(
      FlutterActivity.createDefaultIntent(currentActivity)
    );
  }
});

使用createDefaultIntent来启动activity,系统默认了dart的入口是main()方法,起始的路由是“/”。使用intent时dart的入口不能改变,但是能改变起始路由,下面的例子演示了如何自定义起始路由

myButton.addOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View v) {
    startActivity(
      FlutterActivity
        .withNewEngine()
        .initialRoute("/my_route")
        .build(currentActivity)
      );
  }
});

细心的同学看到了,我们除了改变了路由地址,还添加了一个withNewEngine配置,从字面意思上可以猜出是创建一个新的Flutter Engine,这个FlutterActivity将拥有他自己的FlutterEngine实例。但是这会带来一个问题,FlutterEngine的创建很耗时,也非常消耗资源,如果activity和engine是一对一的关系,那么每次启动都避免不了白屏现象,而且内存会暴增。这肯定是不能接受了,我们的诉求大概有两点:

  1. 只创建一个FlutterEngine,所有的flutter页面共享
  2. FlutterEngine能不能在FlutterActivity打开之前就创建好,这样就能避免白屏现象

为了解决上面两个问题,Flutter为我们带来了cached flutter-engine

3.Cached Flutter Engine

根据你产品的实际情况和需求,在合适的时候创建FlutterEngine,让他先启动并缓存起来,这样我们拿来用的时候就不会有上面两个问题了。

下面的代码演示了在Application中预启动FlutterEngine

public class MyApplication extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    // 初始化FlutterEngine.
    flutterEngine = new FlutterEngine(this);

    // 使用dart executor来预热FlutterEngine.
    flutterEngine.getDartExecutor().executeDartEntrypoint(
      DartEntrypoint.createDefault()
    );

    // 缓存FlutterEngine,并且给一个id,方便后面获取
    FlutterEngineCache
      .getInstance()
      .put("my_engine_id", flutterEngine);
  }
}

我们给FlutterEngine指定id后就可以在使用的时候直接用这个id去获取了,注意不要写错了这个id的名称,建议使用一个常量来保存。

需要注意的是当executeDartEntrypoint方法被调用的时候,意味着你的dart入口函数也被执行了,如果你的main方法里面有runApp,那么你的flutter页面就会运行在一个size为0的window上,直到FlutterEngine依附到FlutterActivity,FlutterView,或FlutterFragment上。所以你需要保证你的app在FlutterEngine预热到真正显示这期间能正常运行。

下面我们来看看在FlutterActivity中如何用过缓存的FlutterEngine:

myButton.addOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View v) {
    startActivity(
      FlutterActivity
        .withCachedEngine("my_engine_id")
        .build(currentActivity)
      );
  }
});

一句话就ok,使用withCachedEngine("my_engine_id"),传入的参数就是在application中定义的id。这时候你再去启动FlutterActivity的时候你会发现白屏的现象几乎没有了,在release模式下效果更佳。

注:

1.当FlutterEngine和FlutterActivity的生命周期是没有任何管理的,当FlutterActivity,FlutterFragment销毁后FlutterEngine依然在运行,如果你想节省资源销毁他,可以在FlutterEngineCache类中通过id去获取到这个FlutterEngine,并调用FlutterEngine.destroy()进行销毁操作。

2.避免白屏现象并不是我们预先启动FlutterEngine的唯一原因,由于FlutterEngine和FlutterActivity是没有关联的,所以只要是启动后你可以在任意时刻执行任意的dart代码,只要不是和UI相关的(毕竟这时候UI还没有显示出来),比如我们可以进行网络请求,缓存数据等。当你做这些操作的时候也不要忘了要遵守android系统的规范

 

今天时间比较紧,只是写了一个皮毛,后续有更深入的研究再来补!

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值