为安卓开发者介绍的移动开发框架 Flutter

我是 TrueFace 的高级软件工程师 Adel Boussaken。今天我要给大家介绍 Flutter 开发。欢迎加入 Dart 阵营。

我将跳过所有有关安装和运行 Flutter 应用程序的部分,直接进行操作,如果您不确定 Flutter 是什么,并且有许多问题,请阅读 关于 Flutter 的演进之路 。

Dart

如果你认为 Kotlin 是 Java 的替代,等到你看到 Dart 后,你会发现它是直截了当,没有样板代码的:

  • 默认为public,通过前缀“_” 进行私有化;
  • 集合; 点击试用
  • 一切都是对象 - 没有“primitives”
  • 命名参数,可选参数,默认值: 点击试用
  • 属性 - 无需在任何地方写“get”方法
  • 级联 - 一切都是构建者
  • 使用 strong mode 类型推导 - 只需要在本地写“var”
  • 命名构造函数,自动分配到字段; 点击试用
  • 字符串插值,几种类型的字符串; 点击试用
  • dartfmt - 如果不想格式化 也可以不用这个工具

这里有一个 Dart 代码的例子,一个获取 IP 地址的私有方法:

_getIPAddress() async {
    String url = 'https://httpbin.org/ip';
    var httpClient = createHttpClient();
    var response = await httpClient.read(url);
    Map data = JSON.decode(response);
    String ip = data['origin'];
}

设计模式

我很确定你已将你的 Android 技巧从无序代码扩展到 MVC、MVP、MVVM,Dagger2、DataBinding 和 Android 架构组件 ,Flutter 基本上就是一个 V(View),响应式视图,它可以是无状态或有状态的 widget,就连 AppCompatActivity 也是一个 widget。

让我们创建一个非常简单的 Activity,我们需要一个文本视图和一个更新该文本的按钮,下面是 Activity 代码(注意没有 XML):

public class Click extends Activity {
    int count = 0;
    protected void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.main);
        final Button button = (Button) findViewById(R.id.button);
        final TextView text = (TextView) findViewById(R.id.counter);
        button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                count++;
                text.setText("Button clicked " + counter + " times");
            }
        });
    }
}

在 Flutter,你不需要操纵视图,就像 setText() 中的代码,你可以使用 state 来替代,并且 Flutter 将会处理好屏幕更新,在 Flutter 中和上述代码等价的是:

import 'package:flutter/material.dart';class Activity extends StatefulWidget {
  @override
  ActivityState createState() => new ActivityState();
}class ActivityState extends State<Activity> {
  int counter = 0;
  @override
  Widget build(BuildContext context) {    return new Scaffold(
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[            new Text(
              'Button clicked ${counter} times',
            ),            new FlatButton(
              child: new Text('Increment'),
              onPressed: () {
                setState(() {
                  counter++;
                });
              },
            ),
          ],
        ),
      ),
    );
  }
}

你也注意到,我们在 setState 中增加了 counter 的值,一旦 onPressed 被触发(之后是 setState),Flutter 将会使用新的 counter 值来重新渲染整个 widget 和 text 对象。

分离 widget 和 state(对于 Android 开发人员来说)的最大优点是,如果你在 Java 代码中旋转设备或调整窗口大小(支持多窗口),则计数器的值将被重置为零,你必须编写大量重复代码来管理 Activity 的生命周期。而在 Flutter 中,这是不需要的,现成的功能,无需额外的代码。

虽然 Dart 最终编译为 native 代码,但它不会访问硬件设备,例如,如果你要获取用户位置,你必须使用 平台 通道编写特定平台的代码,与此同时,确实有很多插件来处理这些情况,但你依然希望登录Android Studio(或 Xcode)在代码之间完成该事项。

Async/Await

在 Android 开发中,UI 线程非常重要,完成速度稍慢的事情工作,会显示以下神秘行:

I/Choreographer(1378): Skipped 55 frames!  The application may be doing too much work on its main thread.

这种情况你只能使用线程来处理,如下所示:

public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            // a potentially  time consuming task
            final Bitmap bitmap =
                    processBitMap("image.png");
            mImageView.post(new Runnable() {
                public void run() {
                    mImageView.setImageBitmap(bitmap);
                }
            });
        }
    }).start();
}

上述代码可以很简单的使用 Dart 完成:

onClick() async {
  Bitmap bitmap = await processBitMap("image.png");
  // you don't want to update non-existent widget
  if (!mounted) return;
  setState(() {
    imageView = bitmap;
  });
}

这里发生了什么? async 修饰符标记的方法会安排稍后执行,该方法变成非阻塞的,因此你的应用程序不会丢失任何帧,await 修饰符挂起方法的执行,等待 processBitMap 完成,然后执行将会恢复。

Widget

目前有大量在 Android 之上运行的各种 OEM 软件和皮肤,这都是可以理解的,因为每个制造商都希望为其设备建立自己的附加值,我不能计算我究竟说了多少次“Funck S*ms*ng”,OEM 定制对 Android 开发人员引入了很多难题.。

Flutter,为了实现 120FPS 的目标,已决定开始在一个空的画布上,使用 Skia 2D 图形库绘制每个 widget,而不是重用 OEM widget,并实现大多数 Material Designa 和通用 layout。

这种方法,无法保证你的应用程序在多种设备上看起来是一样的,尽管并不是所有的 Flutter widget 都经过优化,可以在平板电脑上也可以在较小屏幕的设备上正常工作。

无论如何,这种方法也为 UI 设计的创新打开了新的大门,例如,以下的代码可以使得用户改变 Activity 的大小:

class HeroScreen extends StatefulWidget {
  @override
  HeroState createState() => new HeroState();
}class HeroState extends State<HeroScreen> with SingleTickerProviderStateMixin {

  bool _scaling = false;

  Matrix4 _transformScale = new Matrix4.identity();
  double scalePos = 1.0;  set _scale(double value) =>
      _transformScale = new Matrix4.identity()..scale(value, value, 1.0);

  @override
  Widget build(BuildContext context) {    return new Scaffold(
        body: new GestureDetector(
            onScaleStart: (details) {
              setState(() {
                _scaling = true;
              });
            },
            onScaleUpdate: (details) {              var n = details.scale;
              setState(() {
                scalePos = n;
                _scale = n;
              });
            },
            onScaleEnd: (details) {
              setState(() {
                _scaling = false;
                _scale = scalePos < 1 ? 1.0 : scalePos;
              });
            },
            child: new Container(
                color: Colors.black26,
                child: new Transform(
                    transform: _transformScale,
                    child: new Center(
                        child: new Row(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: <Widget>[                          new Text(_scaling ? "Scaling" : "Scale me up"),
                        ]))))));
  }
}

这让我们得到一个非常有趣的小部件,这样去写可重复使用的小部件就太容易了, 我可以将以上不太友好的代码转换成可重用且干净的小部件:

class Scale extends StatefulWidget {  final Widget child;  final GestureScaleStartCallback onStart;  final GestureScaleEndCallback onEnd;  final GestureScaleUpdateCallback onUpdate;

  Scale({Key key, this.child, this.onStart, this.onUpdate, this.onEnd})
      : super();

  @override
  ScaleState createState() => new ScaleState();
}class ScaleState extends State<Scale> with SingleTickerProviderStateMixin {
  Matrix4 _transformScale = new Matrix4.identity();
  double scalePos = 1.0;  set _scale(double value) =>
      _transformScale = new Matrix4.identity()..scale(value, value, 1.0);

  @override
  Widget build(BuildContext context) {    return new GestureDetector(
        onScaleStart: widget.onStart,
        onScaleUpdate: (details) {
          widget.onUpdate(details);          var n = details.scale;
          setState(() {
            scalePos = n;
            _scale = n;
          });
        },
        onScaleEnd: (details) {
          widget.onEnd(details);
          setState(() {
            _scale = scalePos < 1 ? 1.0 : scalePos;
          });
        },
        child: new Container(
            color: Colors.black26,
            child: new Transform(
                transform: _transformScale, child: widget.child)));
  }
}

重构后的代码如下:

class HeroScreen extends StatefulWidget {
  @override
  HeroState createState() => new HeroState();
}class HeroState extends State<HeroScreen> with SingleTickerProviderStateMixin {
  bool _scaling = false;

  @override
  Widget build(BuildContext context) {    return new Scaffold(
        body: new Scale(
      onStart: (details) => setState(() => _scaling = true),
      onUpdate: (details) {},
      onEnd: (details) => setState(() => _scaling = false),
      child: new Container(
          color: Colors.black26,
          child: new Center(
              child: new Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[                new Text(_scaling ? "Scaling" : "Scale me up"),
              ]))),
    ));
  }
}

Etc

  • 即时运行称为热重新加载,需要不到一秒钟
  • Flutter 使用 CPU 绘制图形、使用 GPU 渲染, 但是一些关于 3D 的 API 是不可用的
  • 不用 XML 来设计布局
  • 布局只需一次性计算树的大小
  • 即使有语法错误,您的 APP 也不会崩溃
  • Flutter 小部件可以嵌入到 Android Activity 中
  • 您不能在 Flutter 小部件中嵌入 Android 库
  • 至少需要 60 FPS,除非你的机器正在做别的事情
  • 受到 React 的启发设计 了API,但不是像 React 那样运行的
  • 不需要任何 POJO  

    原文发布时间为:2017-10-10

    本文作者:佚名

    本文来自合作伙伴“51CTO”,了解相关信息可以关注。

时间: 2024-10-04 11:14:14

为安卓开发者介绍的移动开发框架 Flutter的相关文章

安卓开发者之殇:应用频遭山寨 广告收益被抢夺

中介交易 SEO诊断 淘宝客 云主机 技术大厅 山寨应用泛滥 安卓开发者之殇 正规应用频频被山寨,该自己赚的钱被他人拿走 IT时报 李栋 安卓系统的开放性和免费性等特征,让开发者和用户趋之若鹜,用户也渐渐习惯了安卓应用的这种"免费午餐".但在免费的背后,却有着巨大的安全阴影. 正规应用频频被"顶包" "他们完全盗用了我们爱范儿的官方LOGO,连介绍内容都一模一样.",面对"爱范儿"应用的山寨版本,爱范儿的一位负责人对此怒不可遏

安卓开发者之殇:正规应用频遭山寨 广告收益被抢夺

山寨应用泛滥 安卓开发者之殇 正规应用频频被山寨,该自己赚的钱被他人拿走 IT时报 李栋 安卓系统的开放性和免费性等特征,让开发者和用户趋之若鹜,用户也渐渐习惯了安卓应用的这种"免费午餐".但在免费的背后,却有着巨大的安全阴影. 正规应用频频被"顶包" "他们完全盗用了我们爱范儿的官方LOGO,连介绍内容都一模一样.",面对"爱范儿"应用的山寨版本,爱范儿的一位负责人对此怒不可遏.他对<IT时报>记者说道,近期在小

PostgreSQL介绍以及如何开发框架中使用PostgreSQL数据库

最近准备下PostgreSQL数据库开发的相关知识,本文把总结的PPT内容通过博客记录分享,本随笔的主要内容是介绍PostgreSQL数据库的基础信息,以及如何在我们的开发框架中使用PostgreSQL数据库,希望大家多多提意见. 1.PostgreSQL数据库介绍 PostgreSQL是以加州大学伯克利分校计算机系开发的 POSTGRES,现在已经更名为PostgreSQL.它具有很多不错的特点: 开源:PostgreSQL 是一个自由的对象-关系数据库服务器(数据库管理系统),它在灵活的 B

安卓开发者们受邀为Chrome OS做好准备

Google将要把Play带入Chrome OS,使Chromebook用户可以使用安卓应用和媒介. Google在2010年展示了第一个Chromebook原型,第二年则将第一批商用笔记本电脑上市.五年后,Chromebook设法占领了一部分在美国的市场份额,其中学校现在"比起所有其他的设备加起来,购买了更多的Chromebook",并且在2016年Q1中"Chromebook超越了Mac",这都是Google引用了IDC的话.其中一个解释Chromebook被大

腾讯热拥全球安卓开发者大会 或掀移动应用分发热潮

备受瞩目的2013安卓全球开发者大会(AndroidWorld)将于本月29日在深圳揭幕.作为移动端最具价值的产品之一,移动应用分发的身影不会缺席.记者获悉,在移动应用分发领域重点发力的腾讯,届时将赴会开设"腾讯开放平台移动应用分发"主题分论坛,与移动应用开发者.终端厂商等产业精英分享观点.深入探讨. 2013安卓全球开发者大会将以"领衔互联创新, 智享移动世界"为主题,针对安卓系统智能终端下一阶段发展方向与规划.移动互联网时代智能终端新业务等议题进行广泛交流,全面

为ASP开发者介绍ColdFusion

ColdFusion是一个稳定.可靠的Web应用服务平台.自从1995年Allaire公司第一次发布ColdFusion以来,它已经成功地证明了自己优秀的可伸缩性.跨平台能力,成为Web应用开发领域的主流力量之一.因此,作为Web应用开发者我们至少应该对ColdFusion有一个基本的了解. 一.脚本基础 作 者 : 仙人掌工作室 ColdFusion使用的服务器端脚本语言称为Cold Fusion Markup Language(CFML,ColdFusion标签语言).CFML的语法以HTM

向Java开发者介绍Scala

Scala结合了面向对象编程与函数编程思想,使用一种能够完全兼容Java.可以运行在Java虚拟机上的.简洁的语法.对于函数编程风格的支持,尤其是对于Lambda表达式的支持,能够有助于减少必须要编写的逻辑无关固定代码,也许让它可以更简单的关注要面对的任务本身,而相对的Java中对Lamdba表达式的支持要到预定于2012年发布的JavaSE8才会实现.本文就是对于Scala介绍. 相关厂商内容 Flash Builder 4.5高级版试用版免费高速下载 QClub(北京站)--<云计算与虚拟化

2014安卓全球开发者大会热点揭晓

2014安卓全球开发者大会最新议程出炉,演讲嘉宾阵容非常强悍,集合了高德.联通.腾迅.海尔.多盟.百度.豌豆荚.中手游.AVOS CLOUD.七牛.ARM.微软.云巴.极客学院等业内知名企业的高管精英.在现场您会看到IDG联合中国联通共同发起的"未来家庭娱乐联盟"签约仪式,您还能与风靡大江南北的脸萌的CEO郭列近距离接触,感受他辛酸又美妙的创业经历.这将是移动互联网产业链全方位的思想碰撞与融合. 一年一度的移动开发者盛宴--2014安卓全球开发者大会将于10月23-24日在深圳福田香格

开发者应该多关注安卓吗?

很干脆地说,当然应该关注安卓!安卓有那么庞大的用户量,是一个绝不容忽视的平台.当然,我们可以选择不做安卓版本,可以选择绕开,但是决不会在策略上完全忽视安卓. 可是,再高的装机量.再大的下载量,也不能让人对安卓平台没有收费渠道这一点视而不见.在这个世界的大多数国家,google play是可以收费的;可是在天朝,google play--对不起,google play是什么?大部分的安卓手机连google play都没有啊,更不用说收费渠道了.没有收费渠道,开发商靠什么来盈利呢?不能盈利,又开发了