为什么要有混合开发
我们知道,Flutter是可以做跨平台开发的,即一份Flutter的Dart代码,可以编译到多个平台上运行。这么做的好处就是,在不降低多少性能的情况下,尽最大可能的节省开发的时间成本,直接将开发的时间总成本缩短了快一半,而且测试也比较轻松,通常情况下,在一端能正常运行,在另外的端也不会有太大问题,不会出现由于开发水平不一致导致的,版本功能没有对齐的尴尬局面。然而完全的跨平台开发,在某些对性能要求极高的场景表现则不尽人意,特别是Android的低端机上。那么有没有一种方案,既能保留跨平台开发高效的优点,又能在特定的功能上充分发挥原生的优势呢?如果没有,我就不会在这里扯淡了。这个完美的解决方案就是混合开发。
什么是混合开发
混合开发简单来说就是,既有Flutter的Dart代码,又有平台相关的原生代码,如Kotlin、Swift。在改动比较小,且追求极致体验的主要功能模块,采用原生开发,搭建一个所谓的“壳”。然后在一些经常变动的界面,如应用的首页、活动页面,以及简单的UI界面,如设置界面、关于界面,使用Flutter进行开发。这样做的好处就是可以降低错误率,提高开发效率,缩减开发周期,提升产品竞争力和快速抢占市场的能力。
混合开发长啥样
使用Flutter进行混合开发的app,性能不比原生差多少。而且在比较难的领域,只需要攻克Flutter端的代码,就可以。如Web3,不是说它有多难,主要是比较前沿,会的人相对来说较少。
开始集成Flutter模块到Android端
由于本人水平有限,我这里只介绍Android端的混合开发。我这里默认你已经掌握了Flutter的跨平台开发。如果没有这个基础的同学,可以看我Flutter专栏的其他文章。
- 创建项目
你要先创建一个android app原生工程。然后在原生工程的里面再创建一个Flutter的模块项目。特别注意的是,Project type从Application改为Module,直接以模块的方式进行依赖和编译。Platforms至少选择Android,调试可能会用到Web,更方便。 - Flutter模块的gradle配置
在settings.gradle中加入以下代码。
然后加入以下代码。setBinding(new Binding([gradle: this])) evaluate(new File( settingsDir,'flutter_lib/.android/include_flutter.groovy')) include ':flutter_lib'
注意将FAIL_ON_PROJECT_REPOS改为PREFER_SETTINGS。dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS) repositories { google() mavenCentral() maven { allowInsecureProtocol = true url "http://download.flutter.io" } } }
如果为Gradle8.x,加入namespace,8.x之前使用applicationId。在flutter_lib->.android->Flutter->build.gradle中加入以下代码。
命名空间可以自己定义。android { namespace 'com.example.flutter_lib' }
- 在app模块中依赖该flutter模块,跟依赖普通的android模块一样。
dependencies { implementation project(':flutter') }
- 在app模块的AndroidManifest.xml清单文件中注册FlutterActivity。
如果你有使用我的1.1版本以上的dora框架[https://github.com/dora4/dora] ,则这一步略过。<application> <activity android:name="io.flutter.embedding.android.FlutterActivity" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize" /> </application>
- 打开Flutter插件的入口Activity。
val intent = FlutterActivity .withNewEngine() .initialRoute("home") .build(this) startActivity(intent)
后续
你还可以将插件的UI风格设计得跟原生的壳一样,然后封装好常用的原生的功能,使用Flutter的MethodChannel进行通信,提供给Flutter层进行调用。如打开原生的WebView,弹出原生的对话框,获取系统状态栏的高度等。另外Flutter模块项目,就不要依赖一些跨平台的库了,如deviceinfo,在Android这边没法获取到iOS那边的设备信息。