一个 iOS 开发者的 Flutter“历险记” - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MobService
V2EX    自言自语

一个 iOS 开发者的 Flutter“历险记”

  •  
  •   MobService 2019-05-17 16:01:20 +08:00 562 次点击
    这是一个创建于 2338 天前的主题,其中的信息可能已经有所发展或是发生改变。

    1、 官方简介

    Flutter 是谷歌的移动 UI 框架,可以快速在 iOS 和 Android 上构建高质量的原生用户界面。

    官方介绍: 快速开发: 毫秒级的热重载,修改后,您的应用界面会立即更新。使用丰富的、完全可定制的 widget 在几分钟内构建原生界面。 富有表现力和灵活的 UI: 快速发布聚焦于原生体验的功能。分层架构允许您完全自定义,从而实现难以置信的快速渲染和富有表现力、灵活的设计 原生性能: Flutter 包含了许多核心的 widget,如滚动、导航、图标和字体等,这些都可以在 iOS 和 Android 上达到原生应用一样的性能。

    2、安装环境

    ①下载 FlutterSDK: https://github.com/flutter/flutter/releases

    ②配置 vscode 编辑器: https://flutterchina.club/get-started/editor/#vscode 附:vs 下载地址

    ③vscode 命令运行 flutter doctor,会提示你设置 flutterSDK 路径 (如果遇到权限问题需要用 Sudo chown 命令,如果遇到文件夹不存在需要手动创建对应的文件夹)

    ④构建第一个 Flutter 程序: 创建程序 :VSCode -> View -> Command palette : Flutter NewProject 运行程序 :Debug -> Start Debuging

    注意事项 :如果遇到 Multiple commands produce 错误,cocoapods 导入问题,尝试修改 build system:在 Xcode 菜单栏 -> File -> Workspace Setting,将 build system 修改为 legacy build system,然后 clean 后编译。 ⑤Hello World!: void main() => runApp(Center(child:Text("hello,world!",textDirection: TextDirection.ltr))); Pubspec Format 介绍: https://www.dartlang.org/tools/pub/pubspec

    3、Widget 介绍

    官方布局介绍: https://flutterchina.club/tutorials/layout/

    链接: https://flutterchina.club/widgets-intro/

    基础 Widget: MaterialApp:该 widget 在应用程序的根部创建了一些有用的 widget,其中包括一个 Navigator, 它管理由字符串标识的 Widget 栈(即页面路由栈)。Navigator 可以让您的应用程序在页面之间的平滑的过渡。

    Scaffold:实现 MaterialDesign 布局 Widget, 此类提供 tabbar,navigationBar 和 bottomSheets 等。

    Row、Column: 这些具有弹性空间的布局类 Widget 可让您在水平( Row )和垂直( Column )方向上创建灵活的布局。其设计是基于 web 开发中的 Flexbox 布局模型。

    Stack: 取代线性布局 (译者语:和 Android 中的 LinearLayout 相似),Stack 允许子 widget 堆叠, 你可以使用 Positioned 来定位他们相对于 Stack 的上下左右四条边的位置。Stacks 是基于 Web 开发中的绝度定位( absolute positioning )布局模型设计的。

    Container:Container 可让您创建矩形视觉元素。container 可以装饰为一个 BoxDecoration, 如 background、一个边框、或者一个阴影。Container 也可以具有边距( margins )、填充(padding)和应用于其大小的约束(constraints)。另外,Container 可以使用矩阵在三维空间中对其进行变换。

    当然还有常用的其他一些 Widget 就不一一罗列了,exam:Padding、Image、Clip...

    https://flutterchina.club/widgets/

    但是有必要说一下:Cupertino 系列 Widget 是基于 iOS 设计语言的 Widget 风格

    4、动画

    官方详细介绍: https://flutterchina.club/animations/

    个人总结: Flutter 动画不同于 iOS 动画,一个 block 执行一个动画

    Flutter 的动画的核心类为: AnimationController:控制动画的开始,暂停,与结束,它不关心我在执行什么动画

    Animation:这个是一个抽象类,决定动画的数据和变化方式等,可以通过 addListener 去监听其 Value 的变化,初始化的时候需要一个 AnimationController ;

    开始一段动画过程: ①AnimationController.forward();//开始动画 ②Animation.value 发生变化,并执行 Animation.notifyListener() ③监听函数执行 setState() ④子 Widget 根据 Animation 的 value 值进行布局

    总结:就是不停的根据 Animation 的变化进行 setState(),Flutter 的动画并不关心 Widget 的布局方式等,只提供动画的数据模型

    5、界面跳转 使用了 Navigator 和 Routes。一个路由是 App 中“屏幕”或“页面”的抽象,而一个 Navigator 是管理多个路由的 widget。你可以粗略地把一个路由对应到一个 UIViewController。Navigator 的工作原理和 iOS 中 UINavigationController 非常相似,当你想跳转到新页面或者从新页面返回时,它可以 push() 和 pop() 路由。

    两种方式跳转: △构建路由表 void main() { runApp(MaterialApp( home: MyAppHome(), // becomes the route named '/' routes: <String, WidgetBuilder> { '/a': (BuildContext context) => MyPage(title: 'page A'), '/b': (BuildContext context) => MyPage(title: 'page B'), '/c': (BuildContext context) => MyPage(title: 'page C'), }, )); }//跳转 Navigator.of(context).pushNamed('/b'); △直接通过 widget 创建一个路由 Navigator.push(context, new MaterialPageRoute( builder: (BuildContext context) => new FTShareHomePage(title: "ShareSDK Flutter Bridge"), // fullscreenDialog: true, )); △数据回传 //比如 push 到位置选择界面 Map coordinates = await Navigator.of(context).pushNamed('/location');//用户选择了位置 pop 出来 Navigator.of(context).pop({"lat":43.821757,"long":-79.226392});

    6、Dart 中的异步

    ①先了解代码怎么写 Future<map> loadData() async { String dataURL = "https://jsonplaceholder.typicode.com/posts"; http.Response respOnse= await http.get(dataURL); return json.decode(response.body); }//调用 loadData().then((Map data){</map>

    }); ② 原理其实不重要 (手动滑稽) 官方介绍: Dart 是单线程执行模型,但是它支持 Isolate (一种让 Dart 代码运行在其他线程的方式)、事件循环和异步编程。除非你自己创建一个 Isolate,否则你的 Dart 代码永远运行在 UI 线程,并由 event loop 驱动。Flutter 的 event loop 和 iOS 中的 main loop 相似 Looper 是附加在主线程上的。 Dart 的单线程模型并不意味着你写的代码一定是阻塞操作,从而卡住 UI。相反,使用 Dart 语言提供的异步工具,例如 async / await,来实现异步操作。

    7、与原生进行交互

    官方介绍链接: https://flutterchina.club/platform-channels/

    介绍 应用的 Flutter 部分通过平台通道( platform channel )将消息发送到其应用程序的所在的宿主( iOS 或 Android )。 宿主监听的平台通道,并接收该消息。然后它会调用特定于该平台的 API (使用原生编程语言)

    代码示例(分享到第三方平台): dart 代码怎么写 //创建一个 channel static const channel = const MethodChannel('com.mob.flutter/sharesdk');// invokeMethod 方法执行原生方法 static Future<map> share(int platform, Map params) async { return await channel.invokeMethod("share", [platform, params]); } 原生层:</map>

    • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [GeneratedPluginRegistrant registerWithRegistry:self];

      FlutterViewController* cOntroller= (FlutterViewController*)self.window.rootViewController; FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"com.mob.flutter/sharesdk" binaryMessenger:controller]; [channel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) {
      dispatch_async(dispatch_get_main_queue(), ^{
      if ([call.method isEqualToString:@"share"]) { NSMutableDictionary *params = @{}.mutableCopy; NSArray *args = call.arguments; [params SSDKSetupShareParamsByText:args.lastObject[@"text"] images:args.lastObject[@"images"] url:args.lastObject[@"url"] title:args.lastObject[@"title"] type:SSDKContentTypeAuto]; [ShareSDK share:[args.firstObject integerValue] parameters:params onStateChanged:^(SSDKResponseState state, NSDictionary *userData, SSDKContentEntity *contentEntity, NSError *error) {
      NSMutableDictionary *dic = @{}.mutableCopy; dic[@"state"] = @(state); dic[@"userData"] = userData; dic[@"contentEntity"] = contentEntity.dictionaryValue; dic[@"error"] = error.userInfo; if (result) { result(dic); } }]; } });

      }];
      return [super application:application didFinishLaunchingWithOptions:launchOptions]; } 注意: 通道的客户端和宿主通过通道构造函数中传递的通道名称进行连接。单个应用中使用的所有通道名称必须是不同的; 我们建议在通道名称前加一个特殊的“域名前缀”,例如 samples.flutter.io/battery ( flutter 中文网 google 翻译害死人) setMethodCallHandler 回调不在主线程

    8、开发 Package

    官方介绍链接: https://flutterchina.club/developing-packages/

    步骤: ①创建一个 Package 工程 flutter create --template=package hello#指定 org 可以自动创建平台桥接文件和 example 示例 path_to_fluttersdk/bin/flutter create --org com.yoozoo --template=plugin sharesdk ②实现 package:lib/<package name="">.dart 下为插件的 flutter 端代码,ios/Classes/HelloPlugin.m 下为 原生层实现代码,初始代码已有 bridge 示例</package>

    ③启动 xcode,插件 bridge 文件在 Pods/Development Pods/hello/Classes/下:在编辑 Xcode 中的 iOS 平台代码之前,首先确保代码至少已经构建过一次(例如,从 Xcode 中运行示例应用程序或终端执行 cd hello/example; flutter build ios --no-codesign )。

    ④自动生成 api 文档: cd package 工程目录 export FLUTTER_ROOT=~/dev/flutter$FLUTTER_ROOT/bin/cache/dart-sdk/bin/dartdoc ⑤发布前检查: //过程会提示你完善 pubspec.yaml,关于 example 和 test 的警告可无视 flutter packages pub publish --dry-run ⑥发布: flutter packages pub publis

    关于分包: 对于 ShareSDK 和支付这样的 Plugin 需要分包且 cocoapods 含有 subspec 的,需要开发者在设置完 dependences 后手动去 packageName.podspec 设置对应的依赖,然后运行 Flutter upgrade package

    To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html#Pod::Spec.new do |s|

    s.name = 'sharesdk_flutter' s.version = '0.0.1' s.summary = 'flutter plugin for sharesdk.' s.description = 'ShareSDK is the most comprehensive Social SDK in the world,which share easily with 40+ platforms.' s.homepage = 'http://www.mob.com' s.license = { :file => '../LICENSE' } s.author = { 'Mob' => '[email protected]' } s.source = { :path => '.' } s.source_files = 'Classes/**/' s.public_header_files = 'Classes/**/.h' s.dependency 'Flutter' s.dependency 'mob_sharesdk'# s.dependency 'mob_sharesdk/ShareSDKUI'# s.dependency 'mob_sharesdk/ShareSDKPlatforms/QQ'# s.dependency 'mob_sharesdk/ShareSDKPlatforms/SinaWeibo'# s.dependency 'mob_sharesdk/ShareSDKPlatforms/WeChat'# s.dependency 'mob_sharesdk/ShareSDKPlatforms/Facebook'# s.dependency 'mob_sharesdk/ShareSDKPlatforms/Twitter'

    s.ios.deployment_target = '8.0'end 附: ShareSDK 官方 package 主页: https://pub.dartlang.org/packages/sharesdk

    个人学习 Demo github 地址: https://github.com/vhbvb/Flutter_learn

    ShareSDK package 开发 git: https://github.com/MobClub/ShareSDK-For-Flutter

    目前尚无回复
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5939 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 34ms UTC 06:29 PVG 14:29 LAX 23:29 JFK 02:29
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86