这里我已经创建了一个API 27的Android模拟器,如果你的列表为空,点击图中Create Virtual Devices...
创建模拟器即可。
运行Dart代码
第一步中我们已经写好了代码,第二步中我们的模拟器也启动了,点击AndroidStudio工具栏中的Run
按钮即可运行Flutter项目到我们的模拟器中了,Run
按钮在下图所示位置:
稍等片刻,模拟器中就会自动安装并打开我们的第一个Flutter App了,如下图所示:
可以看到,我们仅仅用了20多行代码,就完成了一个精美的Demo App(虽然没有实现任何功能,但是对比下如果要用Android或iOS原生开发方式,可以做到这么简单实现吗),这一切都归功于Flutter为我们提供的Widgets,下面的篇幅里会针对常用的Widgets做一些讲解。
Flutter项目结构
新创建的Flutter项目的结构如下图所示:
各个目录/文件说明如下:
.
├── README.md —markdown项目描述文件
├── android —Android源代码目录
├── build —项目构建后输出的相关文件目录
├── flutter_app.iml —项目相关的配置文件
├── flutter_app_android.iml —Android相关的配置文件
├── ios —iOS源代码目录
├── lib —Dart源码目录
├── pubspec.lock —安装锁定文件
├── pubspec.yaml —flutter依赖配置文件,类似Android中的build.grale
└── test —测试代码目录
我们开发的代码主要存放在lib/
目录下,项目的入口文件main.dart
也在lib/
目录下。
Flutter App是怎样的App
关于一个Flutter App,你需要了解如下几个点:
- Flutter App的布局文件都是使用Dart代码来写的(业务逻辑代码和UI代码都用dart来写),没有像Android中的xml布局文件或者iOS中的xib, storyboard文件等。
- Flutter App中的界面都是由Widget组成的,Widget分为两种:StatefulWidget和StatelessWidget。StatefulWidget表示一个有状态的组件,这个组件的状态发生改变时,组件UI会同步发生改变;StatelessWidget表示一个无状态的组件,它没有状态的改变,UI也不会发生改变。如果你熟悉Reactjs,对Flutter中的这两种组件就很容易理解了。
- Dart是一门单线程语言,这意味着在Flutter开发过程中你不用去考虑线程的同步异步、锁、线程切换等问题,网络请求也好,UI更新也好,都在一个线程中执行,只不过那些比较耗时的操作(网络IO,文件IO等等)会被放入延迟运算队列中以免阻塞了其他的操作而造成卡顿。
- Flutter跟ReactNative或者WEEX这类移动端跨平台框架最大的区别在于:Flutter通过AOT(Ahead of Time)或者JIT(Just In Time)的方式(Debug模式下采用JIT编译,Release模式下使用AOT编译)将Dart代码直接编译成对应平台的代码用于在移动设备上执行,而ReactNative、WEEX则是有一套自己的jsRender,将js代码通过渲染引擎渲染成原生的UI,这个过程有js和native的互操作,也就是一个jsBridge,所以ReactNative或者WEEX虽然写出来的也是原生应用,但是由于有了jsBridge的存在,导致代码运行的效率没有直接编译成原生代码的Flutter App的运行效率高。
Flutter常用Widgets
在移动开发中,我们经常会跟按钮、文本输入框、图片等打交道,Flutter中也不例外,使用Flutter开发的App,界面上的每一个UI元素都是一个Widget,通过不同的Widget组合形成一整个页面。除了按钮、输入框、图片等Widget外,Flutter还给我们提供了很多功能强大,界面美观的Widget,比如在本文最开始的一段代码:
// main.dart文件内容
import ‘package:flutter/material.dart’;
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: ‘Flutter Demo’,
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new Scaffold(
appBar: new AppBar(
title: new Text(‘First App’)
),
body: new Center(
child: new Text(‘Hello world’),
),
),
);
}
}
在上面的代码中,MyApp
是我们自定义的一个类,它继承自StatelessWidget,代表它是一个无状态的组件,UI不会发生改变。build
方法是父类的一个方法,被MyApp
类重写了,继承自