初识
第一次接触Flutter是在2019年底。
Flutter发布时间不长, 当时没有深入的接触,尝试着装了开发环境,诸如遇到了很多问题Java安装、AndroidStudio安装、FlutterSDK下载、被墙等。
看着文档查着资料一步步的去解决,所幸最后安装成功了,运行了Deom,因为当时在做其他项目没有做更深入的接触。
随后,因手中的项目已经上线有了空余时间,加上公司要开发新项目并鼓励使用Flutter来做,便开始了Flutter的研究及开发。
由于之前搭建过环境的机器已更换,所以又重新搭建了Flutter环境在新的Mac上,也借此机会重新熟悉了一次环境搭建过程并做了文字记录,便于日后查找并发布到了平台上。
欢迎交流,记录见:Mac安装Flutter开发环境。
Flutter因其多平台的统一性使得公司及个人开发者而言有明显的经济性效益提升。
语言转换感言
因为之前一直在做iOS开发,项目大多用Objective-C少量涉及Swift,而Flutter是Google基于Dart语言开发的,Dart语言相较于Objective-C差别还是很大的,都说Objective-C是计算机语言中一个另类,其实也不为过。
学习资料推荐
编辑器选择
iOS:Xcode(也只能用Xcode,是一款很优秀的编辑器)
Flutter:VSCode、Android Studio等,经过这一段时间的使用个人认为在Mac上使用VSCode更好一些,页面过度平滑,使用时卡顿很少而且各种配置功能很多,文件创建等相对便捷。
语言规则的对比
属性声明
Objective-C:
@property(nonatomic, assign) NSUInteger saveLimit;
@property(nonatomic, weak) id<DRLLogDelegate> delegate;
Dart:
int connectTimeout = 10000;
Map headers = {};
方法声明
Objective-C:
- (void)addLog:(nonnull NSString *)content;
Dart:
processObtainRequest({NetworkRequest request}) {}
对象创建
Objective-C:
DRLLogMessage *message = [DRLLogMessage new];
Dart:
Dio dio = Dio();
方法回调
Objective-C:
/// 接收回调
[commodityPuchaseGoodsRequest startWithSuccess:^(DNResponse *response) {
} failure:^(NSError *error) {
}];
/// 发起回调
- (void)startWithSuccess:(DNRequestSuccessBlock)success failure:(DNRequestFailureBlock)failure {
__weak typeof(self) weakSelf = self;
DNResponse * response = [DNResponse new];
NSError *parseError = [NSError new];
if(success) {
success(response);
}
if (failure) {
failure(parseError);
}
}
Dart:
/// 接收回调
MineInformationUpdateGenderRequest(gender: age).start((response) {
}, (errorResponse) {
});
/// 发起回调
post(String urlPath, {Map<String, dynamic> parameter, Map<String, String> header, ResponceSuccess successBlock, ResponceError failureBlock, NetworkContentType contentType = NetworkContentType.applicationJson}) async {
Response response;
Map lastMap = parameter;
try {
response = await _dio.post(urlPath, data: lastMap);
if (successBlock != null) {
successBlock(response);
}
} on DioError catch (error) {
Response errorRespones;
if (failureBlock != null) {
failureBlock(errorRespones);
}
}
}
工程建立
iOS:
Xcode创建
Flutter:
终端、Android Studio VScode等
设计模式的选择
iOS 一些小型项目通常采用MVC结构 中大型项目会采用MVVM等结构
Flutter因底层结构生命周期和内存管理机制会在设计模式上与iOS所使用的有些不同。
代理模式
iOS
///Log.h
@protocol LogDelegate <NSObject>
@optional
- (void)newLogMessage:(DRLLogMessage *)logMessage;
@end
@interface Log : NSObject
@property(nonatomic, weak) id<LogDelegate> delegate;
+ (instancetype)sharedLog;
@end
///Log.m
@implementation DRLLog
- (void)addLogWithType:(DRLLogType)type title:(nullable NSString *)title desc:(nullable NSString *)desc {
if ([weakSelf.delegate respondsToSelector:@selector(newLogMessage:)]) {
[weakSelf.delegate newLogMessage:message];
}
}
@end
///delegate.m
@interface DRLLogBrowseViewController ()<LogDelegate>
@property(nonatomic, strong) Log *logManager;
@end
@implementation DRLLogBrowseViewController
- (void)createContent {
self.logManager = [DRLLog sharedLog];
self.logManager.delegate = self;
}
- (void)newLogMessage:(DRLLogMessage *)logMessage {
//Do
}
@end
Flutter 要使用到 mixin 的超类
mixin NetworkInterceptorsDelegate {
void onRequestDone(RequestOptions options, RequestInterceptorHandler handler);
void onResponseDone(Response response, ResponseInterceptorHandler handler);
void onErrorDone(DioError err, ErrorInterceptorHandler handler);
}
class NetworkLog with NetworkInterceptorsDelegate {
void onRequestDone(RequestOptions options, RequestInterceptorHandler handler) {
//Do
}
}
class NetworkInterceptors {
NetworkInterceptorsDelegate delegate;
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
// TODO: implement onRequest
super.onRequest(options, handler);
if (delegate != null) {
delegate.onRequestDone(options, handler);
}
}
}
代码管理
iOS Flutter基本一致 Git SVN都适用;
第三方框架、插件的使用和选择
Flutter因其高度的开源性非常收到开发者们的青睐,有很多优秀的开源项目开源框架在Github中,且开发势头有暴增的趋势,
Flutter开发常用第三方库分享
UI搭建的转变
Flutter有着高度封装的UI模块,很多样式都可以找到现成的官方或第三方已搭建好的样式,
列表加载优化
生命周期
iOS生命周期
AppDelegate
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary<UIApplicationLaunchOptionsKey,id> *)launchOptions {
return YES;
}
//在App启动时调用表示应用加载进程已经开始,常用来处理应用状态的存储和恢复。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
// 表示App将从未运行状态进入运行状态,用于对App的初始化操作。
- (void)applicationDidBecomeActive:(UIApplication *)application{}
// 当应用即将进入前台运行时调用。
- (void)applicationWillResignActive:(UIApplication *)application{}
// 当应用开始在后台运行的时候调用。
- (void)applicationDidEnterBackground:(UIApplication *)application{}
// 当程序从后台将要重新回到前台(但是还没变成Active状态)时候调用。
- (void)applicationWillEnterForeground:(UIApplication *)application{}
// 已经从后台进入前台
- (void)applicationDidBecomeActive:(UIApplication *)application{}
// 当前应用即将被终止,在终止前调用的函数。通常是用来保存数据和一些退出前的清理工作。如果应用当前处在suspended,此方法不会被调用。 该方法最长运行时限为5秒,过期应用即被kill掉并且移除内存。
- (void)applicationWillTerminate:(UIApplication *)application{}
控制器(ViewController)
// 1.init初始化
- (instancetype)init{
if (self = [super init]) {
}
return self;
}
// 2.Nib加载成功 当时xib加载时
- (void)awakeFromNib{
[super awakeFromNib];
}
// 3.加载view。
- (void)loadView{
[super loadView];
}
// 4.载入完成,可以进行自定义数据以及动态创建其他控件
- (void)viewDidLoad {
[super viewDidLoad];
}
// 5.视图将出现在屏幕之前
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
}
// 6.将要对子视图进行调整
- (void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
}
// 7.对子视图进行调整完毕
- (void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
}
// 8.视图已在屏幕上渲染完成
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
}
// 9.视图将被从屏幕上移除
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
}
// 10.视图已经被从屏幕上移除
- (void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
}
// 11.视图被销毁,此处需要对你在init和viewDidLoad中创建的对象进行释放
- (void)dealloc{
}
// 12.内存警告
- (void)didReceiveMemoryWarning{
[super didReceiveMemoryWarning];
}
视图(View)
// 1.当视图添加子视图时调用
- (void)didAddSubview:(UIView *)subview{
[super didAddSubview:subview];
}
// 2.当子视图从本视图移除时调用
- (void)willRemoveSubview:(UIView *)subview{
[super willRemoveSubview:subview];
}
// 3.当视图即将加入父视图时 / 当视图即将从父视图移除时调用
- (void)willMoveToSuperview:(nullable UIView *)newSuperview{
[super willMoveToSuperview:newSuperview];
}
// 4.当视图加入父视图时 / 当视图从父视图移除时调用
- (void)didMoveToSuperview{
[super didMoveToSuperview];
}
// 5.当视图即将加入window视图时 / 当视图即将从window视图移除时调用
- (void)willMoveToWindow:(nullable UIWindow *)newWindow{
[super willMoveToWindow:newWindow];
}
// 6.当视图加入window视图时 / 当视图从window视图移除时调用
- (void)didMoveToWindow{
[super didMoveToWindow];
}
Flutter Widget 生命周期
内存管理机制
iOS:采用引用计数器对内存进行管理;分为手动引用计数(MRC)和自动引用计数(ARC),OC的内存机制可以简单概括为:谁持有(retain)谁释放(release)。retain引用计数+1,release反之。
Flutter:而在Flutter中与之对应的是另外一套内存管理机制,垃圾收集器;与Java有一些相似的地方
也整理了一部分关于这方面的资料: Flutter:内存管理机制(内存释放、垃圾回收机制)
网络
iOS
AFNetworking,作为一个成熟的第三方方案被运用到绝大多数iOS项目中,在实际开发中我们一般会对AFNetworking进行业务层的二次封装,以便我们拓展出符合业务场景的功能。
Flutter
dio
针对dio我做了一些二次封装:Flutter 网络层封装(dio封装)
这层封装更多的是偏向于实际中的项目开发,更适用于一些中大型项目;
图片加载
iOS
SDWebImage,成熟的第三方网络图片加载方案,有针对图片加载的多极缓存优化,列表图片加载的优化,图片缓存管理等,功能丰富实用简单;
Flutter
cached_network_image,
Flutter开发中遇到的问题
在实际开发中遇到的问题做了整理归纳:Flutter开发相关问题汇总
未完待续