文档章节

入坑Flutter ,弃坑React-Native(简单体验)

她吃西红柿
 她吃西红柿
发布于 2018/08/15 11:38
字数 2048
阅读 3.4W
收藏 9
前言

由于业务需要之前用react-native重写了公司项目,中间碰到各种坑,莫名其妙红屏,适配坑,页面刷新坑,打包坑,热更新坑.折磨了两个月终于完成.年初就听说了Flutter,看一下是用Google的Dart语言,据说是有望代替JavaScript这个一周完成的奇葩.咳咳,看了下国内咸鱼团队已经在项目中使用了Flutter技术,这是他们的社区社区博文深入理解flutter的编译原理与优化,想不到竟然如此强大.忍不住就参考官方文档写了个demo

Flutter官网

https://flutter.io/get-started/install/

克隆Flutter仓库

git clone -b beta https://github.com/flutter/flutter.git

配置环境变量

export PUB_HOSTED_URL=https://pub.flutter-io.cn //国内用户需要设置
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn //国内用户需要设置
export PATH= flutter所在目录/flutter/bin:$PATH

可直接将环境变量写入~/.bash_profile文件中执行source $HOME/.bash_profile生效(如果未生效请重启终端或电脑)

配置命令行工具sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer

安装链接设备工具

brew update
brew install --HEAD libimobiledevice
brew install ideviceinstaller ios-deploy cocoapods
pod setup

VScode 配置

搜索dart code安装dart 插件

image

快捷键 shift + command + p 输入 ‘doctor’, 然后选择 ‘Flutter: Run Flutter Doctor’ 验证操作 image

同样 shift + command + p 输入 ‘flutter’, 然后选择 ‘Flutter: New Project’ action 创建一个测试项目 vscode 底部展示附加设备 image

点击Debug>Start Debugging即可运行项目

image

image

创建

按照之前的方法创建一个模板 shift + command + p 输入 ‘flutter’, 然后选择 ‘Flutter: New Project’ action

替换 lib/main.dart. 删除lib / main.dart中的所有代码,然后替换为下面的代码,它将在屏幕的中心显示“Hello World”

//应用入口 
//main函数使用了(=>)符号, 这是Dart中单行函数或方法的简写
void main() => runApp(new DemoApp());

class DemoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    
    return new MaterialApp(
      title: 'Welcome to Flutter',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('Welcome to Flutter'),
        ),
        body: new Center(
          child: new Text('Royce and Owen'),
        ),
      ),
      
    );
  }
}

外部包使用

  • 您可以 在pub.dartlang.org上找到english_words软件包以及其他许多开源软件包 image
  • 将english_words添加到pubspec.yaml文件中(pubspec文件
  • 管理Flutter应用程序的assets(资源,如图片、package等)) image
  • 在终端中运行flutter packages get安装依赖
flutter packages get
Running "flutter packages get" in startup_first...           0.6s
  • 导入import 'package:english_words/english_words.dart';
  • 使用 English words 包生成文本来替换字符串“Hello World”.
  • 修改代码
class DemoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final wordPair = new WordPair.random();
    return new MaterialApp(
      title: 'Welcome to Flutter',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('Welcome to Flutter'),
        ),
        body: new Center(
          child: new Text(wordPair.asUpperCase),
        ),
      ),
      
    );
  }
}

添加一个 有状态的部件(Stateful widget)

Stateless widgets 是不可变的, 这意味着它们的属性不能改变 - 所有的值都是最终的.

Stateful widgets 持有的状态可能在widget生命周期中发生变化. 实现一个 stateful widget 至少需要两个类:

  1. 一个 StatefulWidget类。
  2. 一个 State类。 StatefulWidget类本身是不变的,但是 State类在widget生命周期中始终存在.
  • 新建一个组件类RandomWords
  • 新建一个State组件类RandomWordsState
class RandomWordsState extends State<RandomWords> {
  @override
  Widget build(BuildContext context) {
    final wordPair = new WordPair.random();
    return new Text(wordPair.asPascalCase);
  }
}
class RandomWords extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
      // TODO: implement createState
      return new RandomWordsState();
    }
}
  • 修改代码 final wordPair = new WordPair.random(); // 删除此行

class DemoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
   
    return new MaterialApp(
      title: 'Welcome to Flutter',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('Welcome to Flutter'),
        ),
        body: new Center(
          child: new RandomWords(),
        ),
      ),
      
    );
  }
}

创建一个无限滚动ListView

扩展(继承)RandomWordsState类,以生成并显示单词对列表。 当用户滚动时,ListView中显示的列表将无限增长

  1. 在RandomWordsState添加一个变量_suggestions(下划线前缀标识符,会强制其变成私有的)
  2. 添加一个_biggerFont变量来孔子字体大小
  3. 新建_buildSuggestions()方法 显示建议的单词对
  4. 在RandomWordsState中添加一个_buildRow函数
  5. 更新RandomWordsState的build方法以使用_buildSuggestions()
  6. 更新MyApp的build方法
class RandomWords extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return new RandomWordsState();
  }
}
class RandomWordsState extends State<RandomWords> {
  final _suggestions = <WordPair>[];
  final _biggerFont =
      const TextStyle(fontSize: 18.0, color: Color.fromARGB(1, 234, 111, 22));

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text('StartUp'),
        ),
        body: _buildSuggestions());
  }

  Widget _buildSuggestions() {
    return new ListView.builder(
        padding: const EdgeInsets.all(16.0),
        // 对于每个建议的单词对都会调用一次itemBuilder,然后将单词对添加到ListTile行中
        // 在偶数行,该函数会为单词对添加一个ListTile row.
        // 在奇数行,该行书湖添加一个分割线widget,来分隔相邻的词对。
        // 注意,在小屏幕上,分割线看起来可能比较吃力。
        itemBuilder: (context, i) {
          // 在每一列之前,添加一个1像素高的分隔线widget
          if (i.isOdd) return new Divider();
          // 语法 "i ~/ 2" 表示i除以2,但返回值是整形(向下取整),比如i为:1, 2, 3, 4, 5
          // 时,结果为0, 1, 1, 2, 2, 这可以计算出ListView中减去分隔线后的实际单词对数量
          final index = i ~/ 2;
          if (index >= _suggestions.length) {
            _suggestions.addAll(generateWordPairs().take(10));
          }
          return _buildRow(_suggestions[index]);
        });
  }

  Widget _buildRow(WordPair pair) {
    return new ListTile(
      title: new Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
    );
  }
}

添加交互

  1. 添加一个 _saved Set(集合) 到RandomWordsState。这个集合存储用户喜欢(收藏)的单词对
  2. 在 _buildRow 方法中添加 alreadySaved来检查确保单词对还没有添加到收藏夹中。
  3. 同时在 _buildRow()中, 添加一个心形 ❤️ 图标到 ListTiles以启用收藏功能
  4. 在 _buildRow中让心形❤️图标变得可以点击。如果单词条目已经添加到收藏夹中, 再次点击它将其从收藏夹中删除。当心形❤️图标被点击时,函数调用setState()通知框架状态已经改变。
Widget _buildRow(WordPair pair) {
    //判断是否收藏
    final bool alreadySaved = _saved.contains(pair);
    return new ListTile(
      title: new Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
      subtitle: new Text('哈哈哈'),
      trailing: new Icon(
        alreadySaved ? Icons.favorite : Icons.favorite_border,
        color: alreadySaved ? Colors.red : null,
      ),
      onTap: () {
        setState(() {
          if (alreadySaved) {
            _saved.remove(pair);
          } else {
            _saved.add(pair);
          }
        });
      },
    );
  }

导航到新页面

在Flutter中,导航器管理应用程序的路由栈。将路由推入(push)到导航器的栈中,将会显示更新为该路由页面。 从导航器的栈中弹出(pop)路由,将显示返回到前一个路由。这点类似iOS的导航机制

  1. 给AppBar的actions属性添加一个按钮子组件,由于是复数用 <Widget>[]包装
  2. 当用户点击导航栏中的列表图标时,建立一个路由并将其推入到导航管理器栈中。此操作会切换页面以显示新路由在MaterialPageRoute的builder属性中构建,builder是一个匿名函数。
 @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
        actions: <Widget>[
          new IconButton(icon: new Icon(Icons.list), onPressed: _pushSaved)
        ],
          title: new Text('嘿嘿嘿',
              style: const TextStyle(
                  fontSize: 18.0, color: Color.fromRGBO(150, 22, 123, 1.0))),
        ),
        body: _buildSuggestions());
  }
  void _pushSaved() {
    Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
      //便利以保存的单词 创建tile 或者叫(cell,item)
      final tiles = _saved.map((pair) {
        return new ListTile(
          title: new Text(
            pair.asPascalCase,
            style: _biggerFont,
          ),
        );
      });
      final divided =
          ListTile.divideTiles(context: context, tiles: tiles).toList();
          //返回一个新页面
      return new Scaffold(
        appBar: new AppBar(
          title: new Text('saved Suggestions'),
        ),
        body: new ListView(children: divided),
      );
    }));
  }

效果

image

image

使用主题更改UI

创建ThemeData来定义theme

class DemoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Startup Name Generator',
      //主题
      theme: new ThemeData(
        primaryColor: Colors.orange,
      ),
      home: new RandomWords(),
    );
  }
}

ThemeData提供相当多的属性,自定义程度相当高了,不愧是基于OpenGL构建的UI,比起RN自由度高了很多
Material library中的 Colors类也提供了许多可以使用的颜色常量例如Colors.green,Color.fromRGBO(255, 111, 233, 1.0)

部分属性介绍
accentColor → Color 控件的前景色(旋钮、文本、覆盖边缘效果等)。
accentColorBrightness → Brightness 
dividerColor → Color 分隔符和弹窗分隔符的颜色,也用于ListTiles和DataTables的行之间
primaryColor → Color 应用程序主要部分的背景颜色(工具栏,标签栏等)

以上第一flutterdemo完成.
Dart语法非常类似JS,相比较RN但少了</>更加易懂,拥类似state状态机,热加载速度很快,C++底层,基于OpenGL,强大的API和文档支持.

代码地址https://gitee.com/Royce_he/flutter_demo

© 著作权归作者所有

她吃西红柿
粉丝 43
博文 52
码字总数 25812
作品 0
杭州
iOS工程师
私信 提问
加载中

评论(25)

han_beilef
han_beilef

引用来自“Raymin”的评论

搞 Android 就用 Java,搞 iOS 就用 ObjC,踏踏实实地,不会出岔子。
最好连 Kotlin,Swift 都不要用。
提炼出不同平台共用的东西,用 C 或 Lua 等脚本语言写。

引用来自“小麦克”的评论

正解啊,我感觉出了Swift和Kotlin反而让生态混乱了,语言永远不是项目的痛点,真不知道搞出这么多语言干嘛?
赞同,中午英文是否都有缺点,难道因为另外一种语言问题更少,就要替换为一种新语言吗?
1
15001391529

引用来自“墨名次”的评论

一个什么都支持但什么都用得不爽的工具:VSCode。
哈哈 确实
ManderSF
ManderSF
前端浮躁没毛病 层出不穷的技术 学到你学不动为止 最后还是发觉JS JQuery大法好
Jeffhtli
Jeffhtli
我觉得你用Flutter重构完公司的项目,再对比RN会更好!
ApplePeels
ApplePeels
你学习任何一门新的技术 刚开始指定会遇到一堆问题
ApplePeels
ApplePeels
RN真有那么坑吗 不要为了吹捧flutter就恶意贬低rn好不
墨名次
墨名次
一个什么都支持但什么都用得不爽的工具:VSCode。
她吃西红柿
她吃西红柿 博主

引用来自“天选老司机”的评论

我碰到两个问题,不知道博主遇到过没?一个是IOS模拟器经常启动应用后白屏,重启模拟器后偶尔正常,另一个是Flutter的热加载一直没效果,VSCode的Flutter插件也装了
热加载没效果就重新run一遍, 修改类或者新增资源都需要重新运行
她吃西红柿
她吃西红柿 博主

引用来自“溪涧顽石”的评论

我倒是觉得 jsx 语法更清晰呢。。 括号神马的反而有点蒙蒙的。
😝我还觉得OC的中括号[]更优雅
她吃西红柿
她吃西红柿 博主

引用来自“NewAdmin”的评论

写完demo,就觉得括号好多,各种分不清
对啊 各种缩进 不过vscode 那个自动注释提好用的
学 Flutter,能挽救Android 开发吗?

Flutter 是什么 ? Flutter是谷歌的推出的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面。 Flutter可以与现有的代码一起工作。在全世界,Flutter正在被越来越多的开发者和组...

Tamic
2018/11/14
0
0
如何解读 Airbnb 弃用 React Native

最近的技术圈尤为热闹,Google 发布了首个 Flutter 预览版、Vue.js 在 GitHub 上的 star 数量超过了 React.js,而如今全球著名的民宿预订平台 Airbnb 突然宣布要弃 React Native 坑而逃,回归...

程序师
2018/06/30
0
0
全网最全 Flutter 与 React Native 深入对比分析

作为 GSY 开源系列的作者,在去年也整理过 《移动端跨平台开发的深度解析》 的对比文章,时隔一年之后,本篇将重新由 环境搭建、实现原理、编程开发、插件开发、编译运行、性能稳定、发展未来...

恋猫de小郭
2019/06/20
0
0
跨平台项目GSYGithubApp系列三大开源版本推荐(Flutter 、React Native 、Weex)

 跨平台作为移动开发中不可或缺的构成,GSYGithubApp系列一直致力于跨平台开发中的各种尝试,目前已经拥有 GSYGithubAppFlutter 、 GSYGithubAppWeex 、 GSYGithubApp (React Native) 三个版...

恋猫月亮
2018/07/31
0
0
GSY 开源 Flutter 系列一周年

让 GSY 成为你 Flutter 学习路上的“保姆”吧。 Flutter 完整开发实战详解系列文章 开源 Flutter 多案例学习型项目 开源 Flutter 完整实战项目 开源 Flutter 电子书项目 自 2018 年 06 月以来...

恋猫de小郭
2019/06/27
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring Batch 小任务(Tasklet)步骤

Chunk-Oriented Processing不是处理 step 的唯一方法。 考虑下面的一个场景,如果你仅仅需要调用一个存储过程,你可以在 ItemReader 中实现这个调用,然后在存储过程完成调用后返回 null。这...

honeymoose
15分钟前
8
0
Linux日志分析

1. Linux日志文件的类型 2. 系统服务日志 2.1 syslogd的简介 2.2 syslogd的配置和使用 2.3 日志的安全性设置 2.4 远程日志记录服务 3. 日志的轮替 3.1 logrotate简介 3.2 logrotate的配置 3....

JiaMing
昨天
38
0
Raspberry Pi 安装系统

下载系统 https://www.raspberrypi.org/downloads/ 使用卡刷工具 启动时开启 ssh 在卡的 boot 根目录创建 ssh 这个空文件,启动后就打开了 ssh 服务 ➜ boot touch ssh ssh 连接 在路由器里...

郭大鹏
昨天
84
0
5、SpringBoot的Profile功能

1.1、功能介绍 配置文件默认使用application.properties、application-default.properties如果需要指定其他配置文件,可以在命令行参数中指定,spring.profiles.default=xxx 激活profilespr...

神锋
昨天
32
0
设计模式-单例

单例模式分为三种:1.饿汉模式,2.懒汉模式,3.登记模式 饿汉模式:在自己被加载时就将自己实例化,即便加载器是静态的 package singleton; public class EagerSingleton { ...

yiduwangkai
昨天
44
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部