进入我们原生的iOS项目根目录中,为它添加一个git submodule,把我们的flutter项目拉取下来
git submodule add {你的flutter module的仓库地址}git submodule update
在项目的Podfile文件中添加下面的代码,在每次执行pod install会运行podhelper.rb
platform :ios, ‘8.0’
use_frameworks!
target ‘MyApp’ do
pod ‘AFNetworking’, ‘~> 2.6’
xxxx
end
#添加如下两行代码,路径修改为我们的fluter module的路径
flutter_application_path = ‘./flutter-module-demo’
eval(File.read(File.join(flutter_application_path, ‘.ios’, ‘Flutter’, ‘podhelper.rb’)), binding)
打开Xcode关闭bitcode配置Build Settings->Build Options->Enable Bitcode
添加编译脚本,打开Xcode在 Build Phases中添加New Run Script Phase在里面填入如下脚本
“ F L U T T E R R O O T / p a c k a g e s / f l u t t e r t o o l s / b i n / x c o d e b a c k e n d . s h " b u i l d " FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build " FLUTTERROOT/packages/fluttertools/bin/xcodebackend.sh" build"FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh” embed
项目的配置完成现在需要生成一些配置文件
-
进入原生项目的flutter模块目录中执行flutter packages get命令
-
回到原生项目根目录执行pod install
➜ cd flutter-module-demo
➜ flutter-module-demo git:(master) flutter packages get
Running “flutter packages get” in flutter-module-demo… 0.4s
➜ flutter-module-demo git:(master) cd …
➜ FlutterNativeiOS git:(master) ✗ pod install
Analyzing dependencies
Fetching podspec for Flutter
from ./flutter-module-demo/.ios/Flutter/engine
Fetching podspec for FlutterPluginRegistrant
from ./flutter-module-demo/.ios/Flutter/FlutterPluginRegistrant
Downloading dependencies
Using AFNetworking (2.6.3)
Installing Flutter (1.0.0)
Installing FlutterPluginRegistrant (0.0.1)
Generating Pods project
Integrating client project
Sending stats
Pod installation complete! There are 3 dependencies from the Podfile and 3 total pods installed.
到此为止我们的原生项目就已经集成好了flutter项目了。
在原生项目中使用flutter,下面以swift项目为例
修改AppDelegate.swift:注意AppDelegate是集成自FlutterAppDelegate
import UIKit
import Flutter
import FlutterPluginRegistrant // Only if you have Flutter Plugins.
@UIApplicationMain
class AppDelegate: FlutterAppDelegate {
var flutterEngine : FlutterEngine?;
// Only if you have Flutter plugins.
override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.flutterEngine = FlutterEngine(name: “io.flutter”, project: nil);
self.flutterEngine?.run(withEntrypoint: nil);
GeneratedPluginRegistrant.register(with: self.flutterEngine);
return super.application(application, didFinishLaunchingWithOptions: launchOptions);
}
}
修改Controller代码
import UIKit
import Flutter
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(type:UIButtonType.custom)
…
self.view.addSubview(button)
}
@objc func handleButtonAction() {
let flutterEngine = (UIApplication.shared.delegate as? AppDelegate)?.flutterEngine;
let flutterViewController = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)!;
self.present(flutterViewController, animated: true, completion: nil)
}
RUN….
整个的集成过程其实总得来说是如下三个步骤:
-
将flutter项目放入原生项目的文件夹下
-
在podfile中添加podhelper.rb配置
-
在Xcode的build phases添加"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh"iOS编译脚本
其中podhelper.rb文件位于我们flutter模块项目的.ios/Flutter/podhelper.rb下,大家查看它的源码可以发现,它有下面几个作用:
-
把Flutter(flutterEngine)和FlutterPluginRegistrant两个库用pod给原生项目导入进入
-
如果flutter项目有用到flutter plugin插件,把插件用pod导入
-
导入Generated.xcconfig的相关配置信息,在podhelper.rb同级别的目录下还有一个Generated.xcconfig文件,这个文件在使用flutter create xx、flutter run xxx、flutter packages get命令的时候如果该文件不存在则会生成这个文件。这个文件内容如下:
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=/Users/zhiqiangdeng/.flutter_wrapper/1.2.2-pre.43
FLUTTER_APPLICATION_PATH=/Users/zhiqiangdeng/Documents/ProjectSource/XcodeProject/lianhua-order-iOS/order-check-module-flutter
FLUTTER_TARGET=lib/main.dart
FLUTTER_BUILD_DIR=build
SYMROOT=${SOURCE_ROOT}/…/build/ios
FLUTTER_BUILD_NAME=1.0.0
FLUTTER_BUILD_NUMBER=1
他记录了当前flutter sdk的目录位置,以及版本号,还有项目模块的目录位置。这个文件的内容在执行pod install
的时候会被写入到xcode build setting中,在执行完pod install之后,可以在原生项目根目录使用xcodebuild -showBuildSettings|grep flutter
查看相关的信息。
最后一步就是运行程序,运行程序的时候在Build phase添加了xcode_backend.sh该脚本会使用到上面pod install给xcode build setting设置的那些环境变量,然后找到项目目录生成AppFramework。
Android的文章很多,这里不再详细描述了
在原生Android项目中添加子模块,将上面创建的flutter module项目拉取到原生安卓项目中
git submodule add {你的flutter module的仓库地址}
git submodule update
在根目录的settings.gradle中添加如下配置
setBinding(new Binding([gradle: this]))
evaluate(new File(
‘{xxxxx你的flutter module目录}/.android/include_flutter.groovy’
))
在原生项目的app目录下的build.gradle文件中添加Flutter库的依赖
dependencies { implementation project(‘:flutter’)}
在原生代码中集成flutter跳转到flutter页面
我使用了一个新的Activity进行跳转。具体可以参看源码
Button open = findViewById(R.id.openBtn);
open.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setClass(MainActivity.this, MyFlutterActivity.class);
startActivity(intent);
}
});
public class MyFlutterActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flutter);
final FlutterView flutterView = Flutter.createView(
this,
getLifecycle(),
“route1”
);
final FrameLayout layout = findViewById(R.id.flutter_container);
layout.addView(flutterView);
final FlutterView.FirstFrameListener[] listeners = new FlutterView.FirstFrameListener[1];
listeners[0] = new FlutterView.FirstFrameListener() {
@Override
public void onFirstFrame() {
layout.setVisibility(View.VISIBLE);
}
};
flutterView.addFirstFrameListener(listeners[0]);
}
}
Android从原生跳到Flutter模块的黑屏问题,在网上看到很多说设置透明主题的但是没有用,后来看到一种先隐藏显示,等待渲染好第一帧后才显示flutter页面的方法。这里要注意一点要在布局中先把flutter的Container布局设置为InVisible状态,不要使用Gone,用gone的话是不显示也不渲染,用InVisible不显示但是会渲染界面占位置,等待渲染完成后再设置为Visible即可。
在我们的开发过程中遇到了一个问题,就是各个开发者使用的flutter sdk版本不一致,导致一些库无法运行,在网上也遇到有相同问题的人,提出了模仿gradle wrapper来做一个flutter_wrapper的思路。于是我根据自己的需要写了一个flutter_wrapper的小工具。它的主要作用是统一开发人员的本地flutter环境。
使用说明
-
在你的项目根目录中执行命令下载脚本
curl -O https://raw.githubusercontent.com/zakiso/flutterw/master/flutterw && chmod 755 flutterw -
下载好脚本后在根目录中使用
./flutterw init
该命令会收集你当前系统中的flutter版本,并将相关信息写入flutter_wrapper.properties文件中,团队中所有成员都会以该版本号做为该项目的标准版本 -
将flutterw文件和flutter_wrapper.properties文件添加到git中提交到仓库里
-
其他成员拉取代码后在项目中使用flutter命令的地方使用./flutterw代替,如果使用ide请选择home目录下对应版本的sdk包
flutterw做了什么?
-
使用flutterw的时候会获取当前目录下的flutter_wrapper.properties文件中的版本号
-
去用户的${HOME}/flutter_wrapper/{版本号}/ 目录下查找是否有该版本sdk
-
如果没有该版本sdk会下载下来,然后使用该目录下的sdk执行命令
注意事项
如果flutter版本是preview的版本是直接使用master的最新代码来管理的。大家可以查看源码很简单,根据自己的需要定制。
项目demo我已经传到github中:有遇到问题的可以参考项目源码
总结
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
最后送福利了,现在关注我可以获取包含源码解析,自定义View,动画实现,架构分享等。
内容难度适中,篇幅精炼,每天只需花上十几分钟阅读即可。
大家可以跟我一起探讨,有flutter—底层开发—性能优化—移动架构—资深UI工程师 —NDK相关专业人员和视频教学资料,还有更多面试题等你来拿
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
最后送福利了,现在关注我可以获取包含源码解析,自定义View,动画实现,架构分享等。
内容难度适中,篇幅精炼,每天只需花上十几分钟阅读即可。
大家可以跟我一起探讨,有flutter—底层开发—性能优化—移动架构—资深UI工程师 —NDK相关专业人员和视频教学资料,还有更多面试题等你来拿**
[外链图片转存中…(img-behatS24-1712424767072)]