Contenu connexe Similaire à Flutter 是什麼?用 Flutter 會省到時間嗎? @ GDG Devfest2020 (20) Flutter 是什麼?用 Flutter 會省到時間嗎? @ GDG Devfest20203. •Flutter 是什麼? Dart 語⾔?
•Flutter 畫⾯架構介紹
•Flutter ⼀些常⽤的元件
•⽤ Flutter 開發有什麼要注意的?
•我該⽤原⽣開發還是 Flutter 開發?
•結論
⼤綱
5. Dart is a client-optimized programming language
for apps on multiple platforms. It is developed
by Google and is used to build mobile, desktop, server, and
web applications.
Dart is an object-oriented, class-based, garbage-
collected language with C-style syntax. Dart can compile to
either native code or JavaScript. It
supports interfaces, mixins, abstract
classes, reified generics, and type inference.
- Wikipedia
https://en.wikipedia.org/wiki/Dart_(programming_language)
6. Skia Dart Text
Foundation
Animation Painting
Rendering
Widgets
Material
Gestures
Engine
(C++)
Framework
(Dart)
Cupertino
https://docs.google.com/presentation/d/1cw7A4HbvM_Abv320rVgPVGiUP2msVs7tfGbkgdrTy0I/edit#slide=id.g70d668005_2_22
12. import 'package:flutter/material.dart';
void main() => runApp(HelloWorldApp());
class HelloWorldApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Hello World App',
home: Scaffold(
appBar: AppBar(
title: Text('Hello World App'),
),
body: Center(
child: Text('Hello World'),
),
),
);
}
}
StatelessWidget 範例
13. import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
StatefulWidget 範例
15. class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(...);
}
}
StatefulWidget 範例
16. @override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
StatefulWidget 範例
32. StatelessWidget
constructor
build
A single StatelessWidget can build in many
different BuildContexts
StatefulWidget
constructor
createState
A StatefulWidget creates a new State object for
each BuildContext
Widget Lifecycle
https://docs.google.com/presentation/d/1cw7A4HbvM_Abv320rVgPVGiUP2msVs7tfGbkgdrTy0I/edit#slide=id.g70d668005_2_22
40. Future<String> fetchDataA() async {
return Future.delayed(Duration(seconds: 2), () {
return 'dataA';
});
}
Future<String> fetchDataB() async {
return Future.delayed(Duration(seconds: 2), () {
return 'dataB';
});
return 'dataB';
}
Future<String> fetchDataC() async {
return Future.delayed(Duration(seconds: 2), () {
return 'dataC';
});
}
Future
宣告
41. Future
fetchDataA().then((dataA) {
print(dataA);
return fetchDataB();
}).then((dataB) {
print(dataB);
return fetchDataC();
}).then((dataC) {
print(dataC);
}).catchError((error) {
print(error);
});
Future<String> fetchDataA() async {
return Future.delayed(Duration(seconds: 2), () {
return 'dataA';
});
}
Future<String> fetchDataB() async {
return Future.delayed(Duration(seconds: 2), () {
return 'dataB';
});
return 'dataB';
}
Future<String> fetchDataC() async {
return Future.delayed(Duration(seconds: 2), () {
return 'dataC';
});
}
Promise chain 寫法
43. 同步?⾮同步?
Future<String> foo() async {
String dataA = await fetchDataA();
String dataB = await fetchDataB();
String dataC = await fetchDataC();
return dataA + dataB + dataC;
}
Future.wait([fetchDataA(), fetchDataB(), fetchDataC()]).then((value) {
print(value[0]); // dataA
print(value[1]); // dataB
print(value[2]); // dataC
}).catchError((e) {
print(e);
}); ⾮同步寫法
同步寫法
44. Future<String> fetchData() async {
return Future.delayed(Duration(seconds: 2), () {
return 'data';
});
}
import 'package:http/http.dart' as http;
Future<String> fetchData() async {
final response = await http.get('https://example.com/');
return response.body;
}
Http package
55. class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
/// Add 1 to the current state.
void increment() => emit(state + 1);
/// Subtract 1 from the current state.
void decrement() => emit(state - 1);
}
Cubit
56. Cubit
class MyCounter extends StatefulWidget {
@override
_MyCounterState createState() => _MyCounterState();
}
class _MyCounterState extends State<MyCounter> {
CounterCubit _cubit = CounterCubit();
@override
void initState() {
super.initState();
_cubit = CounterCubit();
}
@override
void dispose() {
_cubit.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
// ...
}
}
57. Cubit
@override
Widget build(BuildContext context) {
return Center(
child: Column(
children: [
BlocBuilder<CounterCubit, int>(
cubit: _cubit,
builder: (context, state) {
return Text('Counter value: $state');
}),
MaterialButton(
child: Text('Increment'),
onPressed: () {
_cubit.increment();
}),
MaterialButton(
child: Text('Decrement'),
onPressed: () {
_cubit.decrement();
}),
],
),
);
}
58. abstract class DataBlocState {}
class DataBlocInitialState extends DataBlocState {}
class DataBlocLoadingState extends DataBlocState {}
class DataBlocLoadedState extends DataBlocState {
final String result;
DataBlocLoadedState({this.result});
}
class DataBlocErrorState extends DataBlocState {
final Error error;
DataBlocErrorState(this.error);
}
初始的狀態
載⼊中的狀態
載⼊完成的狀態
錯誤的狀態
abstract class MyBlocEvent {}
class MyBlocLoadEvent extends MyBlocEvent {}
59. class MyDataBloc extends Bloc<MyBlocEvent, DataBlocState> {
MyDataBloc() : super(DataBlocInitialState());
@override
Stream<DataBlocState> mapEventToState(MyBlocEvent event) async* {
if (state is DataBlocLoadingState) {
return;
}
try {
if (event is MyBlocLoadEvent) {
yield DataBlocLoadingState();
String result = await fetchData();
yield DataBlocLoadedState(result: result);
}
} catch (e) {
yield DataBlocErrorState(e);
}
}
}
Bloc
60. class MyBlocWidget extends StatefulWidget {
@override
_MyBlocWidgetState createState() => _MyBlocWidgetState();
}
class _MyBlocWidgetState extends State<MyBlocWidget> {
MyDataBloc _bloc;
@override
void initState() {
super.initState();
_bloc = MyDataBloc();
}
@override
void dispose() {
_bloc.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
// ...
}
}
Bloc
61. Bloc
@override
Widget build(BuildContext context) {
return BlocBuilder<MyDataBloc, DataBlocState>(
cubit: _bloc,
builder: (context, state) {
if (state is DataBlocLoadingState) {
return CircularProgressIndicator();
} else if (state is DataBlocErrorState) {
return Text('Error: ' + state.error.toString());
} else if (state is DataBlocLoadedState) {
return Text("Complete! " + state.result);
}
return MaterialButton(onPressed: () {
_bloc.add(MyBlocLoadEvent());
});
});
}
69. $ flutter clean
$ flutter packages pub upgrade
$ flutter pub run build_runner build
https://stackoverflow.com/a/63328916/3663980
調整 pubspec.yaml
執⾏結果
71. var number: Int? = null
var number2: Int = 1
變數名稱 型態 值
變數名稱 型態 值
有問號
沒有問號
Kotlin
72. int number2 = 1;
變數名稱型態 值
變數名稱型態
值
有問號
沒有問號
int? number = null;
Dart
76. •enum ⽀援度不佳
•沒有 null safety(類似 Java, C#)
•Method extensions ⽀援度不佳
Dart 語⾔⼩缺點
Added in Dart 2.9
Added in Dart 2.7
78. environment:
sdk: ">=2.11.0-9.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
fluttertoast: ^7.1.1
http: ^0.12.0+2
bloc: ^6.0.3
flutter_bloc: ^6.0.5
cached_network_image: ^2.3.2+1
shared_preferences: ^0.5.1+2
firebase_core: ^0.5.0
firebase_analytics: ^6.0.1
firebase_admob: ^0.10.0+1
flutter_svg: ^0.19.0
url_launcher: ^5.4.1
url_launcher_macos: 0.0.1+8
provider: ^4.1.3
flutter_slidable: ^0.5.7
uuid: ^2.2.2
cupertino_icons: ^1.0.0
Flutter 套件
(列出其⼀專案的 pubspec.yaml 為例)