Flutter 开发文档 Flutter实战 Dart 编程语言概览 pub仓库 main函数使用了(=>)符号, 这是Dart中单行函数或方法的简写。
// =>是return语句的简写
add3(a, b) => a + b;
变量以下划线(_)开头,在Dart语言中使用下划线前缀标识符,会强制其变成私有的。
Activity、Fragment、view 在Flutter中等价于Widget.
与Android view区别
Stateless widgets 是不可变的, 这意味着它们的属性不能改变 ,所有的值都是最终的. Stateful widgets(有状态的部件) 持有的状态可能在widget生命周期中发生变化. 实现一个 stateful widget 至少需要两个类:
stateful widget将自身的构建委托给State对象,State对象的build函数负责构建该Widget,当用户交互或数据发生变化时,Widget状态发生改变,调用State的 setState
方法通知它,而后State根据当前的状态信息,重新构建Widget tree
Flutter中通过Row和Column来实现线性布局,类似于Android中的LinearLayout控件 row水平,Column竖直
Stack类似FrameLayout很像,都是可以叠加的现实View flutter中默认组件尺寸单位都是dp double.infinity,可以使宽度占用尽可能多的空间
点击
MaterialApp MaterialApp是我们使用 Flutter开发中最常用的符合Material Design设计理念的入口Widget。你可以将它类比成为网页中的html标签,且它自带路由、主题色等功能。
Scaffold Scaffold通常被用作MaterialApp的子Widget,它会填充可用空间,占据整个窗口或设备屏幕。Scaffold提供了大多数应用程序都应该具备的功能,例如顶部的appBar,底部的bottomNavigationBar,隐藏的侧边栏drawer等。
const Scaffold({
Key key,
this.appBar, // 标题栏
this.body, // 用于显示当前界面主要内容的Widget
this.floatingActionButton, // 一个悬浮在body上的按钮,默认显示在右下角
this.floatingActionButtonLocation, // 用于设置floatingActionButton显示的位置
this.floatingActionButtonAnimator, // floatingActionButton移动到一个新的位置时的动画
this.persistentFooterButtons, // 多状态按钮
this.drawer, // 左侧的抽屉菜单
this.endDrawer, // 右'侧的抽屉菜单
this.bottomNavigationBar,// 底部导航栏。
this.bottomSheet, // 显示在底部的工具栏
this.backgroundColor,// 内容的背景颜色
this.resizeToAvoidBottomPadding = true, // 控制界面内容 body 是否重新布局来避免底部被覆盖,比如当键盘显示的时候,重新布局避免被键盘盖住内容。
this.primary = true,// Scaffold是否显示在页面的顶部
})
AppBar属性 leading 返回键 iconTheme Appbar 上图标的颜色、透明度、和尺寸信息。默认值为 ThemeData.primaryIconTheme centerTitle 标题是否居中显示,默认值根据不同的操作系统,显示方式不一样。 Flutter AppBar(顶端栏)
Button RaisedButton :凸起的按钮,其实就是Android中的Material Design风格的Button ,继承自MaterialButton FlatButton :扁平化的按钮,继承自MaterialButton OutlineButton :带边框的按钮,继承自MaterialButton IconButton :图标按钮,继承自StatelessWidget
SizedBox
banner+list三种实现方式 listView CustomScrollView ScrollView
debugPrint('classList-' + classList.toString());
Navigator.push跳页面
延迟队列
)我们需要用到 async,await,Future 三兄弟来进行处理。 async ,它是一个延迟计算的标志,标志了把这个任务放到了延迟运算的队列(await)中,通过Future进行返回。
比如说我们的网络请求:
// post请求
static Future<Map> post(String url,
{Map<String, String> params, bool saveCookie = false}) async {
if (params == null) {
params = new Map();
}
String _url = Api.BASE_URL + url;
if (OsApplication.cookie != null) {
params['Cookie'] = OsApplication.cookie;
}
http.Response res = await http.post(_url, body: params);
return _dealWithRes(res, saveCookie: saveCookie);
}
在Dart中,有await标记的运算,其结果值都是一个Future对象,Future不是String类型 Dart规定有async标记的函数,只能由await来调用,比如这样: String data = await getData();
//get请求,请求返回值为Future<String>类型,即其返回值未来是一个String类型的值
getData() async {
//async关键字声明该函数内部有代码需要延迟执行
return await http.get(Uri.encodeFull(url), headers: {"Accept": "application/json"}); //await关键字声明运算为延迟执行,然后return运算结果
}
then await会阻塞流程,等待紧跟着的的Future执行完毕之后,再执行下一条语句,而如果用了Future.then这个api,那么就不会等待,直接执行下面的语句,等Future执行完了,再调用then这个方法。
dynamic 所有dart 对象的基础类型,在大多数情况下,不直接使用它 通过它定义的变量会关闭类型检查,这意味着 dynamix x= ‘hal’; x.foo();这段静态类型检查不会报错,但是运行时会crash,因为x 并没有foo() 方法,所以建议大家在编程时不要直接使用dynamic; var 是一个关键字,意思是"我不关心这里的类型是什么",系统会自动判断类型 runtimeType; object 是Dart 对象的基类,当你定义: object o =xxx ;时这个时候系统会认为o是个对象,你可以调用o的toString()和hashCode()方法因为Object 提供了这些方法,但是如果你尝试调用o.foo()时,静态类型检查会运行报错。综上不难看出dynamic 与object 的最大的区别是在静态类型检查上。
将 Flutter 集成到现有应用 Flutter 与 Android 的相互通信
File > New > New Module > flutter 新建到自己项目目录下
可以从Native层调用flutter层的dart代码,也可以在flutter层调用Native的代码,而作为通讯桥梁就是MethodChannel,这个类在初始化的时候需要注册一个渠道值。这个值必须是唯一的,并且在使用到的Native层和Flutter层互相对应。 flutter调用Android 注册
static const nativeChannel =
const MethodChannel('com.example.flutter/native');
flutter
Map<String, dynamic> result = {'message': '我从Flutter页面回来了'};
nativeChannel.invokeMethod('goBackWithResult', result);
Android
MethodChannel nativeChannel = new MethodChannel(flutterEngine.getDartExecutor(), CHANNEL_NATIVE);
nativeChannel.setMethodCallHandler((methodCall, result) -> {
switch (methodCall.method) {
//回调
case "goBackWithResult":
// 返回上一页,携带数据
ActivityManager.getInstance().finishActivity(FlutterActivity.class);
Toast.makeText(this, (String) methodCall.argument("message"), Toast.LENGTH_SHORT).show();
break;
case "getSendParams":
result.success(getSendParams());
break;
default:
result.notImplemented();
break;
}
});
异步
Future getSendParams() async {
String params = await _SendFeedBackState.nativeChannel
.invokeMethod('getSendParams', "");
print("getSendParams:" + params);
}
Android调用flutter Android
Map<String, Object> result = new HashMap<>();
result.put("message", message);
// 创建MethodChannel
MethodChannel flutterChannel = new MethodChannel(flutterEngine.getDartExecutor(), CHANNEL_FLUTTER);
flutterChannel.invokeMethod("onActivityResult", result);
flutter
@override
void initState() {
super.initState();
Future<dynamic> handler(MethodCall call) async {
switch (call.method) {
case 'onActivityResult':
Fluttertoast.showToast(
msg: call.arguments['message'],
toastLength: Toast.LENGTH_SHORT,
);
break;
case 'goBack':
// 返回上一页
if (Navigator.canPop(context)) {
Navigator.of(context).pop();
} else {
nativeChannel.invokeMethod('goBack');
}
break;
}
}
flutterChannel.setMethodCallHandler(handler);
}
使用 ‘尾随逗号’ Flutter中如何使用原生控件或组件 Flutter代码通常涉及构建相当深的树状数据结构,例如在一个build方法中。 为了获得良好的自动格式化,我们建议您采用可选的尾部逗号。添加尾随逗号很简单:始终在函数、方法和构造函数的参数列表末尾添加尾随逗号,以便保留您的编码格式。 这将有助于自动格式化程序为Flutter样式代码插入适当的换行符。
监听特定的
eventeventBus.on<UserLoggedInEvent>().listen((event) {
print(event.user);});
监听所有的
eventeventBus.on().listen((event) {
print(event. runtimeType);});
发送一个
eventeventBus.fire(new UserLoggedInEvent(myUser));
写text先写padding
child: new Padding(
padding: new EdgeInsets.all(10.0),
child: new Text(
'马上登录',
style:
new TextStyle(color: Colors.white, fontSize: 16.0),
),
)),