Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
アプリ開発の新たな選択肢が登場!Google社製Flutterのご紹介
Search
アシアル株式会社
June 24, 2019
Technology
0
660
アプリ開発の新たな選択肢が登場!Google社製Flutterのご紹介
2019年6月25日(火)開催のアシアル技術セミナーでの発表資料
アシアル株式会社
June 24, 2019
Tweet
Share
More Decks by アシアル株式会社
See All by アシアル株式会社
第2回全国商業高校Webアプリコンテスト説明会(2024年3月版)
asial_corp
0
120
第1回全国商業高校Webアプリコンテスト総括
asial_corp
0
500
6ヶ月間の授業でここまでできた。コンテスト参加に向けての授業内容と生徒の様子を紹介!
asial_corp
0
460
アプリ開発を目指した授業づくりについて
asial_corp
0
480
train20231223_mainslide.pdf
asial_corp
0
600
Monaca Education 活用事例セミナー:「Monacaでゲームプログラミング~作品制作事例~」
asial_corp
0
1.2k
おみくじアプリのスライド_20230719版
asial_corp
0
560
2023年度第二弾無料導入説明会
asial_corp
0
490
Monaca Education_活用事例セミナー「Monacaで情報デザイン」
asial_corp
1
510
Other Decks in Technology
See All in Technology
Terraform未経験の御様に対してどの ように導⼊を進めていったか
tkikuchi
2
430
OCI Vault 概要
oracle4engineer
PRO
0
9.7k
スクラム成熟度セルフチェックツールを作って得た学びとその活用法
coincheck_recruit
1
140
OCI Network Firewall 概要
oracle4engineer
PRO
0
4.1k
Engineer Career Talk
lycorp_recruit_jp
0
140
Terraform CI/CD パイプラインにおける AWS CodeCommit の代替手段
hiyanger
1
240
Amplify Gen2 Deep Dive / バックエンドの型をいかにしてフロントエンドへ伝えるか #TSKaigi #TSKaigiKansai #AWSAmplifyJP
tacck
PRO
0
370
Terraform Stacks入門 #HashiTalks
msato
0
350
Evangelismo técnico: ¿qué, cómo y por qué?
trishagee
0
360
Amazon CloudWatch Network Monitor のススメ
yuki_ink
1
200
The Rise of LLMOps
asei
7
1.4k
dev 補講: プロダクトセキュリティ / Product security overview
wa6sn
1
2.3k
Featured
See All Featured
Side Projects
sachag
452
42k
Writing Fast Ruby
sferik
627
61k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
38
1.8k
The Invisible Side of Design
smashingmag
298
50k
Designing the Hi-DPI Web
ddemaree
280
34k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
280
13k
Raft: Consensus for Rubyists
vanstee
136
6.6k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5k
Unsuck your backbone
ammeep
668
57k
Visualization
eitanlees
145
15k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
47
2.1k
Transcript
アプリ開発の新たな選択肢が登場! Google社製Flutterのご紹介 HIROAKI TSUTSUMI 堤 啓彰 <
[email protected]
> アシアル株式会社
堤 啓彰 Tsutsumi Hiroaki エンジニア(主にフロントエンド) 業務で使ったことのある⾔語:JavaScript PHP C# 多少は書ける⾔語:Java Swift
ここ1年ほどは、Cordovaでのアプリ開発 ※ Flutterを業務で使った経験はなし
Flutterとは Cordova/Flutterの⽐較 Dartとは Flutterの基礎 まとめ TODAY’s AGENDA
Flutterとは Cordova/Flutterの⽐較 Dartとは Flutterの基礎 まとめ TODAY’s AGENDA
Flutterとは Google製の、Android/iOS向けのモバイルアプリを 開発できるクロスプラットフォーム開発ツール 2018年12⽉4⽇、バージョン1.0が正式リリース - 現時点での最新版はバージョン1.5.4 Githubでのスター数は67,000超え
Flutterとは > Githubスター数の推移 2018年2⽉27⽇、β版公開
Flutterとは > モバイルアプリだけではないFlutter Flutter for web Flutterのコードからブラウザで実⾏可能な Webアプリケーションを⽣成する技術 - 現在テクニカルプレビュー
Flutterとは > モバイルアプリだけではないFlutter Desktop Embedding for Flutter Flutterのコードからデスクトップアプリケーション (Windows/MacOS/Linux)を⽣成する技術 -
現在開発中
Flutterとは > モバイルアプリだけではないFlutter Flutterを習得すれば、Android/iOSに加えて、 Web/デスクトップアプリケーションも 作れるように
Flutterとは Cordova/Flutterの⽐較 Dartとは Flutterの基礎 まとめ TODAY’s AGENDA
Cordova/Flutterの⽐較 Cordova Flutter 開発⾔語 HTML/CSS/JavaScript Dart レンダリング WebView ネイティブ ホットリロード
不可 可
Cordova/Flutterの⽐較 > レンダリング:Cordova OS(Android/iOS) WebView UI UIはWebViewにより レンダリング ネイティブアプリよりも、 低パフォーマンス
Cordova/Flutterの⽐較 > レンダリング:Flutter OS(Android/iOS) UI UIはネイティブで レンダリング ネイティブアプリと 遜⾊ないパフォーマンス
Cordova/Flutterの⽐較 > ホットリロード ホットリロード ソースコードの変更を、 アプリを再ビルドせず、状態を維持したまま反映 - 修正が(基本的に)1秒未満で反映 - フルリロードしても10秒程度
Cordovaでは現状できない(ブラウザでは可能)
Cordova/Flutterの⽐較 > ホットリロード Demo
Cordova/Flutterの⽐較 Flutterを使えば、ハイパフォーマンスな アプリを、ホットリロードを⽤いて ⾼速に開発可能
Flutterとは Cordova/Flutterの⽐較 Dartとは Flutterの基礎 まとめ TODAY’s AGENDA
Dartとは > Dartの歴史 Googleによりリリース - JavaScriptを代替することが⽬的 - ブラウザへのDartVMの搭載が⽬標 2011
Dartとは > Dartの歴史 Googleによりリリース - JavaScriptを代替することが⽬的 - ブラウザへのDartVMの搭載が⽬標 ブラウザへのDartVMの搭載を断念 2011
2015
Dartとは > Dartの歴史 Googleによりリリース - JavaScriptを代替することが⽬的 - ブラウザへのDartVMの搭載が⽬標 ブラウザへのDartVMの搭載を断念 Googleのフロントエンド開発の標準⾔語としてTypeScriptが採⽤
2011 2015 2017
Dartとは > Dartの歴史 Googleによりリリース - JavaScriptを代替することが⽬的 - ブラウザへのDartVMの搭載が⽬標 2011 2015
ブラウザへのDartVMの搭載を断念 2017 Googleのフロントエンド開発の標準⾔語としてTypeScriptが採⽤ 現在 Flutterの普及とともに、再び注⽬を集める
Dartとは > Dartの特徴 Dartの特徴 • オブジェクト指向 • 静的型付け
Dartとは > サンプルコード class Person { String _firstName; String _lastName;
Person(this._firstName, this._lastName); String getFullName() { return '$_lastName $_firstName'; } } void main() { Person person = Person('Hiroaki', 'Tsutsumi'); print(person.getFullName()); }
Dartとは > Dartを使ってみた所感 所感 • くせがなく、書きやすい • オブジェクト指向を理解していれば、習得は⽤意 • Javaによく似ており、Javaを触ったことがあれば
すぐ馴染める
Dartとは > カスケード記法 カスケード記法 • 同⼀オブジェクトに対する操作を、 戻り値がなくても連続して記述できる記法 • 「..」(ドット2つ)で操作を連結して記述
Dartとは > カスケード記法 var button = querySelector('#confirm'); button.text = 'Confirm';
button.classes.add('important'); button.onClick.listen((e) => window.alert('Confirmed!')); カスケード記法なし
Dartとは > カスケード記法 var button = querySelector('#confirm'); button.text = 'Confirm';
button.classes.add('important'); button.onClick.listen((e) => window.alert('Confirmed!')); カスケード記法なし querySelector('#confirm') ..text = 'Confirm' ..classes.add('important') ..onClick.listen((e) => window.alert('Confirmed!')); カスケード記法あり
Dartとは > なぜDartが採⽤されたのか Dartはコンパイル⽅式として、JIT(Just In Time)と AOT(Ahead Of Time)の両⽅をサポート -
JIT:コンパイル速・パフォーマンス低 - AOT:コンパイル遅・パフォーマンス⾼
Dartとは > なぜDartが採⽤されたのか Dartはコンパイル⽅式として、JIT(Just In Time)と AOT(Ahead Of Time)の両⽅をサポート -
JIT:コンパイル速・パフォーマンス低 - AOT:コンパイル遅・パフォーマンス⾼ 開発時はJITによる開発サイクルの⾼速化 プロダクションではAOTによるパフォーマンス向上 その他にもいくつかの理由があり、詳細は https://flutter.dev/docs/resources/faq#why-did-flutter-choose-to-use-dart (英語)を参照
Flutterとは Cordova/Flutterの⽐較 Dartとは Flutterの基礎 まとめ TODAY’s AGENDA
Flutterの基礎 すべてがWidget
Flutterの基礎 > すべてがWidget FlutterアプリのUIは、Widgetの組み合わせ Widgetの中に⼊れ⼦でWidgetを追加して、 Widget Treeを構成していくことでUIを構築
Flutterの基礎 > すべてがWidget @override Widget build(BuildContext context) { return Scaffold(
appBar: AppBar(title: Text('TODOリ スト')), body: Column( children: <Widget>[...], ), ); }
Flutterの基礎 > すべてがWidget @override Widget build(BuildContext context) { return Scaffold(
appBar: AppBar(title: Text('TODOリ スト')), body: Column( children: <Widget>[...], ), ); }
@override Widget build(BuildContext context) { return Scaffold( ..., body: Column(
children: <Widget>[ Row( children: <Widget>[...], ), Expanded( child: ListView.builder(...), ), ], ), ); } Flutterの基礎 > すべてがWidget
@override Widget build(BuildContext context) { ..., body: Column( children: <Widget>[
Row( children: <Widget>[ Flexible( child: TextField(...), ), Padding(padding: EdgeInsets.only(right: 10.0)), RaisedButton(...), ], ), ..., Flutterの基礎 > すべてがWidget
Flutterの基礎 > 豊富なWidget Flutterは標準で⼤量のWidgetを提供 https://flutter.dev/docs/development/ui/widgets
Flutterの基礎 > 豊富なWidget:マテリアルデザイン https://flutter.dev/docs/development/ui/widgets/material
Flutterの基礎 > 豊富なWidget:Cupertino https://flutter.dev/docs/development/ui/widgets/cupertino
Flutterの基礎 > 豊富なWidget どのようなWidgetがあり、 そのWidgetで何ができるのかを 把握することが重要
Flutterの基礎 StatelessとStateful
Flutterの基礎 > StatelessとStateful Statelessは状態を持たないWidget Statefulは状態を持つWidget 外部との通信やユーザの操作により 状態が変化しないWidgetはStatelessに 状態が変化するWidgetはStatefulに
Flutterの基礎 > Statelessの例 各タスクはStateless • 渡された⽂字列を表⽰しているだけ • ユーザの操作により、 保持している情報は変化しないため
Flutterの基礎 > StatelessWidget class TodoListItem extends StatelessWidget { final int
_index; final String _todo; final Function _removeTodo; TodoListItem(this._index, this._todo, this._removeTodo); @override Widget build(BuildContext context) { return Card( child: ListTile( title: Text(_todo), trailing: IconButton( icon: Icon(Icons.remove_circle, color: Colors.red), onPressed: () => _removeTodo(_index), ), ..., }
Flutterの基礎 > StatelessWidget class TodoListItem extends StatelessWidget { final int
_index; final String _todo; final Function _removeTodo; TodoListItem(this._index, this._todo, this._removeTodo); @override Widget build(BuildContext context) { return Card( child: ListTile( title: Text(_todo), trailing: IconButton( icon: Icon(Icons.remove_circle, color: Colors.red), onPressed: () => _removeTodo(_index), ), ..., } StatelessWidgetを継承
Flutterの基礎 > StatelessWidget class TodoListItem extends StatelessWidget { final int
_index; final String _todo; final Function _removeTodo; TodoListItem(this._index, this._todo, this._removeTodo); @override Widget build(BuildContext context) { return Card( child: ListTile( title: Text(_todo), trailing: IconButton( icon: Icon(Icons.remove_circle, color: Colors.red), onPressed: () => _removeTodo(_index), ), ..., } buildメソッドをoverride
Flutterの基礎 > 状態変化の例
Flutterの基礎 > 状態変化の例
Flutterの基礎 > StatefulWidget final _todos = <String>[]; ... @override Widget
build(BuildContext context) { return Scaffold( ..., RaisedButton( ..., onPressed: () => setState(() => _todos.add(_todo)), ), ], ), ... child: ListView.builder( itemCount: _todos.length, itemBuilder: (BuildContext context, int index) => TodoListItem(index, _todos[index], _removeTodo), ), ...
Flutterの基礎 > StatefulWidget final _todos = <String>[]; ... @override Widget
build(BuildContext context) { return Scaffold( ..., RaisedButton( ..., onPressed: () => setState(() => _todos.add(_todo)), ), ], ), ... child: ListView.builder( itemCount: _todos.length, itemBuilder: (BuildContext context, int index) => TodoListItem(index, _todos[index], _removeTodo), ), ... State(状態)を定義
Flutterの基礎 > StatefulWidget final _todos = <String>[]; ... @override Widget
build(BuildContext context) { return Scaffold( ..., RaisedButton( ..., onPressed: () => setState(() => _todos.add(_todo)), ), ], ), ... child: ListView.builder( itemCount: _todos.length, itemBuilder: (BuildContext context, int index) => TodoListItem(index, _todos[index], _removeTodo), ), ... Stateを更新(タスクを追加)
Flutterの基礎 > StatefulWidget final _todos = <String>[]; ... @override Widget
build(BuildContext context) { return Scaffold( ..., RaisedButton( ..., onPressed: () => setState(() => _todos.add(_todo)), ), ], ), ... child: ListView.builder( itemCount: _todos.length, itemBuilder: (BuildContext context, int index) => TodoListItem(index, _todos[index], _removeTodo), ), ... Stateの更新を検知し、buildが呼ばれる
Flutterの基礎 > StatefulWidget final _todos = <String>[]; ... @override Widget
build(BuildContext context) { return Scaffold( ..., RaisedButton( ..., onPressed: () => setState(() => _todos.add(_todo)), ), ], ), ... child: ListView.builder( itemCount: _todos.length, itemBuilder: (BuildContext context, int index) => TodoListItem(index, _todos[index], _removeTodo), ), ... State(タスク⼀覧)が変化しているため、 ListViewが更新される
Flutterの基礎 Flutterでのアニメーション
Flutterの基礎 > Flutterでのアニメーション Flutterでは、アニメーションもWidget アニメーションに関しても、豊富なWidgetを提供 もちろん、⾃作も可能
Flutterの基礎 > アニメーション例:Opacity
Flutterの基礎 > アニメーション例:Opacity bool _visible = true; @override Widget build(BuildContext
context) { ... body: Center( child: AnimatedOpacity( opacity: _visible ? 1.0 : 0.0, duration: Duration(seconds: 1), child: Container(width: 200.0, height: 200.0, color: Colors.blue), ), ), floatingActionButton: FloatingActionButton( child: Icon(Icons.flip), onPressed: () => setState(() => _visible = !_visible), ),
Flutterの基礎 > アニメーション例:Opacity bool _visible = true; @override Widget build(BuildContext
context) { ... body: Center( child: AnimatedOpacity( opacity: _visible ? 1.0 : 0.0, duration: Duration(seconds: 1), child: Container(width: 200.0, height: 200.0, color: Colors.blue), ), ), floatingActionButton: FloatingActionButton( child: Icon(Icons.flip), onPressed: () => setState(() => _visible = !_visible), ),
Flutterの基礎 > アニメーション例:Opacity bool _visible = true; @override Widget build(BuildContext
context) { ... body: Center( child: AnimatedOpacity( opacity: _visible ? 1.0 : 0.0, duration: Duration(seconds: 1), child: Container(width: 200.0, height: 200.0, color: Colors.blue), ), ), floatingActionButton: FloatingActionButton( child: Icon(Icons.flip), onPressed: () => setState(() => _visible = !_visible), ), Stateを定義
Flutterの基礎 > アニメーション例:Opacity bool _visible = true; @override Widget build(BuildContext
context) { ... body: Center( child: AnimatedOpacity( opacity: _visible ? 1.0 : 0.0, duration: Duration(seconds: 1), child: Container(width: 200.0, height: 200.0, color: Colors.blue), ), ), floatingActionButton: FloatingActionButton( child: Icon(Icons.flip), onPressed: () => setState(() => _visible = !_visible), ), Stateを更新
Flutterの基礎 > アニメーション例:Opacity bool _visible = true; @override Widget build(BuildContext
context) { ... body: Center( child: AnimatedOpacity( opacity: _visible ? 1.0 : 0.0, duration: Duration(seconds: 1), child: Container(width: 200.0, height: 200.0, color: Colors.blue), ), ), floatingActionButton: FloatingActionButton( child: Icon(Icons.flip), onPressed: () => setState(() => _visible = !_visible), ), Stateの変更を検知し、buildが呼ばれる
Flutterの基礎 > アニメーション例:Opacity bool _visible = true; @override Widget build(BuildContext
context) { ... body: Center( child: AnimatedOpacity( opacity: _visible ? 1.0 : 0.0, duration: Duration(seconds: 1), child: Container(width: 200.0, height: 200.0, color: Colors.blue), ), ), floatingActionButton: FloatingActionButton( child: Icon(Icons.flip), onPressed: () => setState(() => _visible = !_visible), ), Opacityの変更に応じて、 アニメーション
Flutterの基礎 > アニメーション例:Container
Flutterの基礎 > アニメーション例:Container double _width = 100; double _height =
100; Color _color = Colors.blue; @override Widget build(BuildContext context) { ... child: AnimatedContainer( width: _width, height: _height, decoration: BoxDecoration(color: _color), duration: Duration(seconds: 1), curve: Curves.easeInOut, ), ... onPressed: () { setState(() { final random = Random(); _width = random.nextInt(300).toDouble(); _height = random.nextInt(300).toDouble(); _color = Color.fromRGBO(random.nextInt(256), random.nextInt(256), random.nextInt(256), 1); });
Flutterの基礎 > アニメーション例:Container double _width = 100; double _height =
100; Color _color = Colors.blue; @override Widget build(BuildContext context) { ... child: AnimatedContainer( width: _width, height: _height, decoration: BoxDecoration(color: _color), duration: Duration(seconds: 1), curve: Curves.easeInOut, ), ... onPressed: () { setState(() { final random = Random(); _width = random.nextInt(300).toDouble(); _height = random.nextInt(300).toDouble(); _color = Color.fromRGBO(random.nextInt(256), random.nextInt(256), random.nextInt(256), 1); }); Stateを定義
Flutterの基礎 > アニメーション例:Container double _width = 100; double _height =
100; Color _color = Colors.blue; @override Widget build(BuildContext context) { ... child: AnimatedContainer( width: _width, height: _height, decoration: BoxDecoration(color: _color), duration: Duration(seconds: 1), curve: Curves.easeInOut, ), ... onPressed: () { setState(() { final random = Random(); _width = random.nextInt(300).toDouble(); _height = random.nextInt(300).toDouble(); _color = Color.fromRGBO(random.nextInt(256), random.nextInt(256), random.nextInt(256), 1); }); Stateを更新
Flutterの基礎 > アニメーション例:Container double _width = 100; double _height =
100; Color _color = Colors.blue; @override Widget build(BuildContext context) { ... child: AnimatedContainer( width: _width, height: _height, decoration: BoxDecoration(color: _color), duration: Duration(seconds: 1), curve: Curves.easeInOut, ), ... onPressed: () { setState(() { final random = Random(); _width = random.nextInt(300).toDouble(); _height = random.nextInt(300).toDouble(); _color = Color.fromRGBO(random.nextInt(256), random.nextInt(256), random.nextInt(256), 1); }); Stateの変更を検知し、buildが呼ばれる
Flutterの基礎 > アニメーション例:Container double _width = 100; double _height =
100; Color _color = Colors.blue; @override Widget build(BuildContext context) { ... child: AnimatedContainer( width: _width, height: _height, decoration: BoxDecoration(color: _color), duration: Duration(seconds: 1), curve: Curves.easeInOut, ), ... onPressed: () { setState(() { final random = Random(); _width = random.nextInt(300).toDouble(); _height = random.nextInt(300).toDouble(); _color = Color.fromRGBO(random.nextInt(256), random.nextInt(256), random.nextInt(256), 1); }); 各Stateの変更に応じて、 アニメーション
Flutterとは Cordova/Flutterの⽐較 Dartとは Flutterの基礎 まとめ TODAY’s AGENDA
まとめ メリット・デメリット l 学習コストは低くはない l Dart⾃体は馴染みやすい l Widgetを使いこなすのが⼤変 l ⽇本語の情報はまだ少ない
l ネイティブアプリに近い パフォーマンス l ホットリロードによる ⾼速な開発サイクル
None