官方地址:介紹了安裝步驟、簡單用法、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 暫時先理解這麼多,後面待工程實踐