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
680
アプリ開発の新たな選択肢が登場!Google社製Flutterのご紹介
2019年6月25日(火)開催のアシアル技術セミナーでの発表資料
アシアル株式会社
June 24, 2019
Tweet
Share
More Decks by アシアル株式会社
See All by アシアル株式会社
大学オリジナルのデジタル学生証アプリ「MyCampus」のご紹介資料
asial_corp
0
38
第2回全国商業高校Webアプリコンテスト説明会(2024年3月版)
asial_corp
0
160
第1回全国商業高校Webアプリコンテスト総括
asial_corp
0
550
6ヶ月間の授業でここまでできた。コンテスト参加に向けての授業内容と生徒の様子を紹介!
asial_corp
0
490
アプリ開発を目指した授業づくりについて
asial_corp
0
520
train20231223_mainslide.pdf
asial_corp
0
620
Monaca Education 活用事例セミナー:「Monacaでゲームプログラミング~作品制作事例~」
asial_corp
0
1.3k
おみくじアプリのスライド_20230719版
asial_corp
0
630
2023年度第二弾無料導入説明会
asial_corp
0
510
Other Decks in Technology
See All in Technology
利用終了したドメイン名の最強終活〜観測環境を育てて、分析・供養している件〜 / The Ultimate End-of-Life Preparation for Discontinued Domain Names
nttcom
2
200
Developers Summit 2025 浅野卓也(13-B-7 LegalOn Technologies)
legalontechnologies
PRO
0
720
AndroidデバイスにFTPサーバを建立する
e10dokup
0
250
(機械学習システムでも) SLO から始める信頼性構築 - ゆる SRE#9 2025/02/21
daigo0927
0
120
エンジニアのためのドキュメント力基礎講座〜構造化思考から始めよう〜(2025/02/15jbug広島#15発表資料)
yasuoyasuo
17
6.8k
『衛星データ利用の方々にとって近いようで触れる機会のなさそうな小話 ~ 衛星搭載ソフトウェアと衛星運用ソフトウェア (実物) を動かしながらわいわいする編 ~』 @日本衛星データコミニティ勉強会
meltingrabbit
0
150
The Future of SEO: The Impact of AI on Search
badams
0
200
偶然 × 行動で人生の可能性を広げよう / Serendipity × Action: Discover Your Possibilities
ar_tama
1
1.1k
一度 Expo の採用を断念したけど、 再度 Expo の導入を検討している話
ichiki1023
1
170
現場で役立つAPIデザイン
nagix
33
12k
プロダクトエンジニア構想を立ち上げ、プロダクト志向な組織への成長を続けている話 / grow into a product-oriented organization
hiro_torii
1
200
オブザーバビリティの観点でみるAWS / AWS from observability perspective
ymotongpoo
8
1.5k
Featured
See All Featured
The Invisible Side of Design
smashingmag
299
50k
Speed Design
sergeychernyshev
27
790
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
160
15k
StorybookのUI Testing Handbookを読んだ
zakiyama
28
5.5k
Practical Orchestrator
shlominoach
186
10k
Rebuilding a faster, lazier Slack
samanthasiow
80
8.8k
Into the Great Unknown - MozCon
thekraken
35
1.6k
GraphQLとの向き合い方2022年版
quramy
44
13k
Bash Introduction
62gerente
611
210k
Docker and Python
trallard
44
3.3k
The Language of Interfaces
destraynor
156
24k
Optimising Largest Contentful Paint
csswizardry
34
3.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