Flutter挖坑基本上参照中文文档,机票✈️。系统:mac。开发工具:VScode。
第一天:安装。
1.前置条件:
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()。
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(
container: renderView,
debugShortDescription: '[root]',
child: rootWidget
).attachToRenderTree(buildOwner, renderViewElement);
}
abstract class StatelessWidget extends Widget {
const StatelessWidget({ Key key }) : super(key: key);
@override
StatelessElement createElement() => StatelessElement(this);
@protected
Widget build(BuildContext context);
}
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)
class RandomWords extends StatefulWidget {
@override
createState() => new RandomWordsState();
}
class RandomWordsState extends State {
}
State类中维护生命周期。
abstract class State 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 {
final _suggestions = []; //总数据
final _saved = new Set(); //保存喜欢的数据
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: [
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。