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
710
アプリ開発の新たな選択肢が登場!Google社製Flutterのご紹介
2019年6月25日(火)開催のアシアル技術セミナーでの発表資料
アシアル株式会社
June 24, 2019
Tweet
Share
More Decks by アシアル株式会社
See All by アシアル株式会社
大学オリジナルのデジタル学生証アプリ「MyCampus」のご紹介資料
asial_corp
0
60
第2回全国商業高校Webアプリコンテスト説明会(2024年3月版)
asial_corp
0
210
第1回全国商業高校Webアプリコンテスト総括
asial_corp
0
600
6ヶ月間の授業でここまでできた。コンテスト参加に向けての授業内容と生徒の様子を紹介!
asial_corp
0
530
アプリ開発を目指した授業づくりについて
asial_corp
0
540
train20231223_mainslide.pdf
asial_corp
0
640
Monaca Education 活用事例セミナー:「Monacaでゲームプログラミング~作品制作事例~」
asial_corp
0
1.4k
おみくじアプリのスライド_20230719版
asial_corp
0
700
2023年度第二弾無料導入説明会
asial_corp
0
530
Other Decks in Technology
See All in Technology
AWS CDK 実践的アプローチ N選 / aws-cdk-practical-approaches
gotok365
6
680
PHPでWebブラウザのレンダリングエンジンを実装する
dip_tech
PRO
0
200
標準技術と独自システムで作る「つらくない」SaaS アカウント管理 / Effortless SaaS Account Management with Standard Technologies & Custom Systems
yuyatakeyama
3
1.2k
Clineを含めたAIエージェントを 大規模組織に導入し、投資対効果を考える / Introducing AI agents into your organization
i35_267
4
1.5k
プロダクトエンジニアリング組織への歩み、その現在地 / Our journey to becoming a product engineering organization
hiro_torii
0
120
Definition of Done
kawaguti
PRO
6
470
Uniadex__公開版_20250617-AIxIoTビジネス共創ラボ_ツナガルチカラ_.pdf
iotcomjpadmin
0
160
地図も、未来も、オープンに。 〜OSGeo.JPとFOSS4Gのご紹介〜
wata909
0
100
Node-RED × MCP 勉強会 vol.1
1ftseabass
PRO
0
140
原則から考える保守しやすいComposable関数設計
moriatsushi
3
530
本当に使える?AutoUpgrade の新機能を実践検証してみた
oracle4engineer
PRO
1
140
[TechNight #90-1] 本当に使える?ZDMの新機能を実践検証してみた
oracle4engineer
PRO
3
160
Featured
See All Featured
Done Done
chrislema
184
16k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
45
7.4k
Six Lessons from altMBA
skipperchong
28
3.8k
Building Adaptive Systems
keathley
43
2.6k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
50k
Raft: Consensus for Rubyists
vanstee
140
7k
Writing Fast Ruby
sferik
628
61k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
8
790
What’s in a name? Adding method to the madness
productmarketing
PRO
23
3.5k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
jQuery: Nuts, Bolts and Bling
dougneiner
63
7.8k
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