Flutter环境配置
- Flutter的sdk安装在哪个地方合适?
-
- Flutter的SDK中包含了很多命令行工具, 我们需要配置环境变量, 建议安装到平时放命令行工具的地方.
-
- 如果你的Mac只有一个用户, 安装在家目录
~/flutter
下挺合适, 不用考虑权限
- 如果你的Mac只有一个用户, 安装在家目录
-
- 放在opt时要考虑到权限
- 环境配置
-
- 来到你对应的Shell配置文件进行配置
-
- 如果你使用默认的bash, 那么配置
~/.bash_profile
- 如果你使用默认的bash, 那么配置
-
- 如果你是用zsh(Mac新系统默认是zsh), 那么配置
~/.zshrc
- 如果你是用zsh(Mac新系统默认是zsh), 那么配置
# Flutter 镜像配置, 解决墙的问题
$ export PUB_HOSTED_URL=https://pub.flutter-io.cn
$ export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
- 配置FLutter环境变量
#Flutter 配置
$ export FLUTTER=~/flutter
$ export PATH=$FLUTTER/bin:$PATH
- 配置完成后, 重新打开终端或者输入命令载入配置
# bash则使用.bash_profile
$ source ~/.zshrc
用doctor检测命令, 检测你的Flutter环境是否配置成功
flutter doctor
创建方式的几种方式
-
- 命令行工具
flutter create
- 命令行工具
-
- AS创建
-
- Flutter App
-
- Flutter Module 混合开发
-
- Flutter plugin 插件(带有安卓/iOS原生代码, 不一样)
-
- Flutter Package 三方库(只有Dart代码)
-
- Empty Project 空工程, 测试用
创建项目名称不能用驼峰命名法, 下划线全用小写字母
Linux环境变量的配置问题
- 要让shell找到你的工具.
- Mac上有哪些shell?
-
- 早期的bash 配置文件 ~/.bash_profile
-
- 更加强大的zsh 配置文件 ~/.zshrc
-
which flutter
查看flutter的安装位置 -
flutter doctor
, 此时是shell在调用 - 保证用英文输入法!
- 很多文本编辑器自带了格式
-
$
表示展开变量 - 配置在.bash_profile有什么区别?
- 换成zsh原来的配置文件还在bash_profile, 这是怎么办?
- 建议用哪个shell, 写哪个shell的对应文件.
Flutter2.x实操
- Flutter的代码为啥能在安卓/iOS上同时运行?
-
- iOS/安卓 渲染引擎
-
- RN: 原生UI的基础上, 进行包装, 对于原生的依赖非常大
-
- 不再用原生的UI了, 把渲染引擎安装在了手机里面, 负责解析Dart代码, 渲染界面, 弊端是安装包大, 优点是效率高, 不依赖原生UI; 高度统一
-
- Debug时有热重载, Release中为了适配苹果审核, 没有热更新
[图片上传失败...(image-281edb-1636939943685)]
[图片上传失败...(image-833e16-1636939943685)]
目录放在哪里?
-
- 重新选择目录时记得在尾部加上项目名
Dart代码在lib目录下面
AndroidStudio有一个小小的bug
-
- 如果正在执行工程的时候cmd + Q强退锁死, 会锁住当前的运行环境, 再次打开运行时就会出问题, 缓存机制
-
- 这时需要删除缓存文件
flutte/bin/cache
, 删除lockfile
- 这时需要删除缓存文件
入口是
main.dart
的main函数material库, 类似于iOS的UIKit.
万物皆是Widget, 类似于iOS的UIView
flutter之所以效率高, 核心渲染机制里面的增量渲染
iOS里想要某个UI控件发生变化, 给变量里的某个属性赋值; flutter里面相当于改变的不是控件里的成员属性, 谁变了去渲染谁, 直接改变的是控件本身, 上层的渲染树不变, 就没有了iOS的图层!, 后面如果不会改变, 就会适时提示用
const
.逆向就不能从UI入手, 因为脱离了原生.
无状态
stateless
的Widget不可变, 有状态stateful
的Widget内部小部件可以变化状态.本质上都是无状态, stateless的变种封装
类名是驼峰, 工程文件名是小写下划线
自定义的小部件要能被渲染显示出来, 必须重写
build
方法AS快捷键
-
-
Alt + Enter
, 把提示写出来
-
-
-
cmd -
折起
-
-
-
cmd +
打开
-
热重载, Flutter的一个优点是即使项目很大了, 改了一个东西, 由于增量渲染只改增量文件, 点击热重载按钮就能立刻渲染
渲染树发生了变化, 热更新就没有了意义, 需要重新启动
有状态的StatefulWidget, 状态不能清零, 想要状态清零需要重新启动
import 'package:flutter/material.dart'
void main() {
runApp(
const Center(
child: Text(
'hello flutter',
textDirection: TextDirection,ltr
),
)
);
}
void main() => runApp(MyWidget());
class MyWidget extends StatelessWidget {
@overrid
Widget build(BuildContext context) {
return const Center(
child: Text(
'helloFlutter',
textDirection: TextDirection.rtl,
)
)
}
}
Flutter中的文字样式
- Text()是调用了一个构造函数
- OC中是 UIView *view = UIView的构造方法
- Flutter中不是把成员属性暴露给你,
final
修饰的最终变量只能被赋值一次 - 只改变某一个Widget的值
- iOS中界面和对象是分开的, Flutter中整个界面是一个树状的
- 创建一个模型对象, 不渲染, 通过模型对象创建新的Widget界面对象, 替换掉后渲染
- 被干掉的控件没有复用的概念, 没有iOS中指针变量指向的用法,
- Colors是一个独立的类, 点上静态属性,
Colors.red
, 文档中可以看到设计 - MaterialApp, Scaffold
- 不会变, 去除警告, 添加
const
- 垂直居中想对于父Widget
void main() => runApp(MyWidget());
class App extends StatelessWidget{
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter标题'),
),
body: MyWidget(),
),
);
}
}
class MyWidget extends StatelessWidget {
@overrid
Widget build(BuildContext context) {
return const Center(
child: Text(
'helloFlutter1122333',
textDirection: TextDirection.rtl,
sytle: TextStyle(
fontSize: 40.0,
fontWeight: FontWeight.bold,
color: Color.fromARGB(0.9, 0, 0, 255),// 命名构造函数
),
)
)
}
}
初探Flutter中的TableView
- 创建文件夹, 文件夹名称和文件都小写
- 类名开头都是大写
-
?
空安全 - 写代码时直接写类名, 敲回车直接就会帮忙引入头文件
-
Opt + Enter
直接帮忙创建类 - Widget的排列只有三种
-
- 横着
-
- 竖着
-
- 叠着
- 怎么看出是异步加载的? 首先显示的是文字, 图片下载好展示
- 找到跟iOS的共性
- flutter官方文档, dart的包Dart packages
[图片上传失败...(image-515bdd-1636939943685)]
import 'package:flutter/material.dart'
import 'model/car.dart'
void main() => runApp(App());
class App extends StatelessWidget{
@override
Widget build(BuildContext context) {
return MaterialApp(
deubgShowCheckedModeBanner: false, // 除去Debug标签
home: Home(),
);
}
}
class Home extends StatelessWidget {
// _的内部是指文件内部
Widget _itemForRow(BuildContext context, int index) {
return Container(
color: Coplors.white,
margin: const EdgeInsets.all(10),
child: Column(
children: [
Image.network(datas[index].imageURL!),
Container(height: 10),
Text(
datas[index].name!,
style: const TextStyle(
fontWeight: FontWeight.w800,
fontSize: 18.0
),
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Scafflod(
backgroudColor: Colors.grey[100],
appBar: AppBar(
title: const Text('标题'),
),
body: ListView.builder(
itemBuilder: _itemForRow,
itemCount: datas.length
),
);
}
}
final List datas = [
const Car(
name: '保时捷'
imageURL: 'https://img0.baidu.com/it/u=1875746338,171164291&fm=253&fmt=auto&app=120&f=JPEG?w=846&h=477',
),
const Car(
name: '奔驰'
imageURL: 'https://img0.baidu.com/it/u=2269620487,3600909808&fm=253&fmt=auto&app=120&f=JPEG?w=667&h=500',
),
const Car(
name: '宝马'
imageURL: 'https://img1.baidu.com/it/u=1628168174,64924477&fm=253&fmt=auto&app=120&f=JPEG?w=890&h=500',
),
];
class Car{
const Car(this.name, this.imageURL);
final String name;
final String imageURL;
}
最终效果截图
Tips
Flutter的特点
-
- 不依赖原生UI, 拥有独立的渲染引擎
-
- 界面更新逻辑和原生不一样(增量渲染), 重新创建一个新的Widget
为什么Flutter中大量的
final
(只能赋值一次, 最终变量)修饰的属性,const
修饰的构造方法(常量对象)-
- 因为Flutter的渲染逻辑是增量渲染, Widget结构是树状结构.
-
- 想改变屏幕内容就直接改变Widget对象(干掉原来的Widget, 重新创建Widget, 实时快速的创建).
-
- 常量对象的创建效率更高!
Scafflod小部件
-
- 带有导航栏(appBar)的小部件
-
- body属性
抽取ListView
listview_demo.dart
import 'package:flutter/material.dart'
import 'model/car.dart'
class ListViewDemo extends StatelessWidget {
// _的内部是指文件内部
Widget _itemForRow(BuildContext context, int index) {
return Container(
color: Coplors.white,
margin: const EdgeInsets.all(10),
child: Column(
children: [
Image.network(datas[index].imageURL!),
Container(height: 10),
Text(
datas[index].name!,
style: const TextStyle(
fontWeight: FontWeight.w800,
fontSize: 18.0
),
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Scafflod(
backgroudColor: Colors.grey[100],
appBar: AppBar(
title: const Text('标题'),
),
body: ListView.builder(
itemBuilder: _itemForRow,
itemCount: datas.length
),
);
}
}