Flutter挖坑基本上参照中文文档,机票✈️。系统:mac。开发工具:VScode。
第一天:安装。
1.前置条件:
- 安装Android Studio 3.0以上版本,并添加Flutter插件。点击下载AS。(安装好了拖到应用程序里,不然flutter doctor的时候会检测不到)
- 安装Vscode,并添加Flutter插件。点击下载VS。
- Xcode
2.获取FlutterSDK。命令行:git clone -b master https://github.com/flutter/flutter.git
3.检查环境是否安装完成:flutter doctor。遇到报错的响应的解决。
brew update
brew uninstall --ignore-dependencies libimobiledevice
brew uninstall --ignore-dependencies usbmuxd
brew install --HEAD usbmuxd
brew unlink usbmuxd
brew link usbmuxd
brew install --HEAD libimobiledevice
brew install ideviceinstaller
brew upgrade cocoapods
pod setup
一切就绪:
4.开挖:第一个Flutter应用。
主要代码全部在lib/main.dart中。
实现流程;创建app-使用外部包-添加有状态的部件-创建无限滚动的listview-添加交互-导航到新页面-使用主题更改UI
1>替换main中的代码。
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp 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('Hello World'),
),
),
);
}
}
分析:dart的运行入口 main();调用runApp()。
- runApp():主要是初始化、挂载元素到渲染树上、渲染。
void runApp(Widget app) { WidgetsFlutterBinding.ensureInitialized() ..attachRootWidget(app) ..scheduleWarmUpFrame(); }
需要传一个自定义Widget。ensureInitialized()方法完成初始化判断。
-
static WidgetsBinding ensureInitialized() { if (WidgetsBinding.instance == null) WidgetsFlutterBinding(); return WidgetsBinding.instance; }
在WidgetsBinding中initInstance()初始化,而instance 的get方法返回的就是WidgetBinding。
-
@override void initInstances() { super.initInstances(); _instance = this; buildOwner.onBuildScheduled = _handleBuildScheduled; window.onLocaleChanged = handleLocaleChanged; window.onAccessibilityFeaturesChanged = handleAccessibilityFeaturesChanged; SystemChannels.navigation.setMethodCallHandler(_handleNavigationInvocation); SystemChannels.system.setMessageHandler(_handleSystemMessage); } /// The current [WidgetsBinding], if one has been created. /// /// If you need the binding to be constructed before calling [runApp], /// you can ensure a Widget binding has been constructed by calling the /// `WidgetsFlutterBinding.ensureInitialized()` function. static WidgetsBinding get instance => _instance; static WidgetsBinding _instance;
在来看attachRootWidget方法:主要是将widget与renderview、RenderObject三者绑定起来,调用attachToRenderTree()。
-
void attachRootWidget(Widget rootWidget) { _renderViewElement = RenderObjectToWidgetAdapter<RenderBox>( container: renderView, debugShortDescription: '[root]', child: rootWidget ).attachToRenderTree(buildOwner, renderViewElement); }
- StatelessWidget类:主要就是build方法。
abstract class StatelessWidget extends Widget {
const StatelessWidget({ Key key }) : super(key: key);
@override
StatelessElement createElement() => StatelessElement(this);
@protected
Widget build(BuildContext context);
}
- MaterialApp类:继承自StatefulWidget。常用的属性home,title,theme,color、等等。官方定义的Material Design风格。
2>使用外部包。pubspec.yaml中添加依赖。以english_words为例:
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
english_words: ^3.1.0
在lib/main.dart中引入:import 'package:english_words/english_words.dart';
3>添加一个有状态的部件(Statefulwidget)
- 实现一个stateful widget 需要两个类,一个是StatefulWidget类。一个是State类。
class RandomWords extends StatefulWidget {
@override
createState() => new RandomWordsState();
}
class RandomWordsState extends State<RandomWords> {
}
State类中维护生命周期。
abstract class State<T extends StatefulWidget> extends Diagnosticable {
T get widget => _widget;
T _widget;
_StateLifecycle _debugLifecycleState = _StateLifecycle.created;
bool _debugTypesAreRight(Widget widget) => widget is T;
BuildContext get context => _element;
StatefulElement _element;
bool get mounted => _element != null;
@protected
@mustCallSuper
void initState() {}
@mustCallSuper
@protected
void didUpdateWidget(covariant T oldWidget) { }
@protected
@mustCallSuper
void reassemble() { }
@protected
void setState(VoidCallback fn) {}
@protected
@mustCallSuper
void deactivate() { }
@protected
@mustCallSuper
void dispose() {}
@protected
Widget build(BuildContext context);
@protected
@mustCallSuper
void didChangeDependencies() { }
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
}
}
主要流程:参考此博主的图原文链接https://www.jianshu.com/p/05af657c13b0
Scaffold类:定义了一个UI脚手架。常用的包括appbar、body、floatingActionButton、backgroundColor、bottomNavigationBar、bottomSheet等等。
4>创建一个无限滚动的ListView。详细看组件-ListView。
5>添加交互:onTap(){setState(){}}
6>导航到新的页面:
MaterialPageRoute类:
Navigator.of(context).push(new MaterialPageRoute())
7>使用主题更改UI。使用ThemeData类修改主题。
全部代码:
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Welcome to Fultter',
theme: new ThemeData(
primaryColor: Colors.pink[100]
),
home: new RandomWords(),
);
}
}
class RandomWords extends StatefulWidget {
@override
createState() => new RandomWordsState();
}
class RandomWordsState extends State<RandomWords> {
final _suggestions = <WordPair>[]; //总数据
final _saved = new Set<WordPair>(); //保存喜欢的数据
final _biggerFont = const TextStyle(fontSize: 18.0); //字体大小
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Startup Name Generator'),
actions: <Widget>[
new IconButton(
icon: new Icon(Icons.arrow_forward_ios),
onPressed: _pushSaved,
)
],
),
body: _buildSuggestions(), //添加listview
floatingActionButton:new Icon(Icons.add_a_photo,color: Colors.red[50],),
backgroundColor:(Colors.yellow[50]),
);
}
void _pushSaved() {
Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
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),
);
}));
}
Widget _buildSuggestions() {
return new ListView.builder(
padding: const EdgeInsets.all(16.0),
itemBuilder: (context, i) {
if (i.isOdd) return new Divider();
final index = i ~/ 2;
if (index >= _suggestions.length) {
_suggestions.addAll(generateWordPairs().take(10));
}
return _buildRow(_suggestions[index]);
},
);
}
Widget _buildRow(WordPair pair) {
//添加每一条内容
final alreadySaved = _saved.contains(pair);
return new ListTile(
title: new Text(
pair.asPascalCase,
style: _biggerFont,
),
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);
}
});
},
);
}
}
第一天的挖坑就这样了。明天开始Widgets。