官方地址:介绍了安装步骤、简单用法、Demo演示,看完官方文档基本可以上手
- Install Steps
- Get The Flutter SDK
- Run Flutter Doctor
- Update your Path
- Platform Setup - Android Studio
- Install the Flutter and Dart Plugins
- Flutter Demo
- How to write a Flutter app that looks natural on iOS, Android, and the web.
- Basic structure of a Flutter app.
- Finding and using packages to extend functionality.
- Using hot reload for a quicker development cycle.
- How to implement a stateful widget.
- How to create an infinite, lazily loaded list.
- How to add interactivity to a stateful widget.
- How to create and navigate to a second screen.
- How to change the look of an app using themes.
Flutter CodeLab:Part One、Part Two、FlutterForAndroid
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Startup Name Generator',
theme: ThemeData(
primaryColor: Colors.green,
),
home: RandomWords(),
);
}
}
class RandomWords extends StatefulWidget {
@override
RandomWordsState createState() => RandomWordsState();
}
class RandomWordsState extends State<RandomWords> {
final _suggestions = <WordPair>[];
final Set<WordPair> _saved = Set<WordPair>();
final _biggerFont = const TextStyle(fontSize: 18.0);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Startup Name Generator'),
actions: <Widget>[
IconButton(icon: Icon(Icons.list), onPressed: _pushSaved),
],
),
body: _buildSuggestions(),
);
}
void _pushSaved() {
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (BuildContext context) {
final Iterable<ListTile> tiles = _saved.map(
(WordPair pair) {
return ListTile(
title: Text(
pair.asPascalCase,
style: _biggerFont,
),
);
},
);
final List<Widget> divided = ListTile.divideTiles(
context: context,
tiles: tiles,
).toList();
return Scaffold(
// Add 6 lines from here...
appBar: AppBar(
title: Text('Saved Suggestions'),
),
body: ListView(children: divided),
); // ... to here.
},
),
);
}
Widget _buildSuggestions() {
return ListView.builder(
padding: const EdgeInsets.all(16.0),
itemBuilder: (context, i) {
if (i.isOdd) return 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 ListTile(
title: Text(
pair.asPascalCase,
style: _biggerFont,
),
trailing: Icon(
alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.red : null,
),
onTap: () {
setState(() {
if (alreadySaved) {
_saved.remove(pair);
} else {
_saved.add(pair);
}
});
},
);
}
}
Flutter Package:https://pub.dev
官方视频教程:https://www.youtube.com/flutterdev
Introduction to Flutter Development Using Dart:https://www.appbrewery.co/p/intro-to-flutter?utm_source=google&utm_medium=website%20banner&utm_campaign=app_brewery
Dart语言官网:https://dart.dev/guides/language
Dart异步编程:http://www.cainiaoxueyuan.com/ymba/16618.html
//appBar点击相应
_pushSaved() {
print("zzzz_pushSave1");
sleepEntrance();
print("zzzz_pushSave2");
}
void sleepEntrance() async {
print("zzzz_sleepEntrance1");
await new Future((){
print("zzzz_sleepInternal1");
sleep(Duration(milliseconds: 5000));
print("zzzz_sleepInternal2");
});
print("zzzz_sleepEntrance2");
}
Future主体会被放入事件队列,但是如果处理事件过长,仍然会存在ANR的风险(MA)
print("start");
Future(() => print("task1"));
final future = Future(() => null);
Future(() => print("task2")).then((_) {
print("task3");
scheduleMicrotask(() => print('task4'));
}).then((_) => print("task5"));
future.then((_) => print("task6"));
scheduleMicrotask(() => print('task7'));
Future(() => print('task8'))
.then((_) => Future(() => print('task9')))
.then((_) => print('task10'));
print("end");
//对应的打印顺序
I/flutter (32068): start
I/flutter (32068): end
I/flutter (32068): task7
I/flutter (32068): task1
I/flutter (32068): task6
I/flutter (32068): task2
I/flutter (32068): task3
I/flutter (32068): task5
I/flutter (32068): task4
I/flutter (32068): task8
I/flutter (32068): task9
I/flutter (32068): task10
main函数先执行,所以start和end先执行,main函数执行过程中,会将一些任务分别加入到EventQueue和MicrotaskQueue中
task7通过scheduleMicrotask函数加入到MicrotaskQueue中,会被先执行,然后开始执行EventQueue
task1被添加到EventQueue中,首先执行task1
通过final future = Future(() => null)创建的future的then被添加到微任务中(还算说的通,先暂时这么理解吧,网上说法没经过验证),微任务被优先执行,所以会执行task6
一次在EventQueue中添加task2、task3、task5被执行
(scheduleMicrotask的调用是作为task3的一部分代码,所以task4是要在task5之后执行的),此处照搬网上说法,但是没有说服我,我觉得then之后的语句不是作为一个独立的任务,而是融合到了Future任务中了,这样解释更合理一点,后面待验证
task8、task9、task10一次添加到EventQueue被执行
//TODO 暂时先理解这么多,后面待工程实践