SlideShare a Scribd company logo
1 of 50
Download to read offline
Flutterを体験してみませんか
OSC 2020 Online/Kyoto
セミナー企画
1
robo
自己紹介
名前
robo (兼高理恵)
好きなもの
モバイル端末
おしごと
アプリの設計から実装まで
所属
GDG Kyoto (staff) WTM Kyoto (staff) Flutter Osaka (staff)
2
はじめに
このセッションは、Flutter 未体験者や初学者向けです。
● Flutter は、どんなものなのかな?
● Flutter を、触ってみたいな。
そんなあなたに、Flutter の概要について紹介します。
GDG Kyoto は、
Google テクノロジーに興味のある 初心者から 専門家の方に、
開発者同士の交流や 新しいスキルへの学びを支援するコミュニティです。❤
Fluttr ⇒ iOS/Android/Web アプリが作れるフレームワーク
3
Flutter とは
4
● Fast Development
ホットリロードでレイアウト変更も
素早く確認
● Expressive and flexible UI
柔軟に組み合わることのできる
ウィジェット&高速レンダリング。
● Native Performance
リリースアプリは、ネイティブマシンコード
(ARM)にビルドされます。
Flutter 公式サイト https://flutter.dev/
5
迅速な開発
6
● Fast development
Flutterのホットリロードは、すばやく簡単に
実験、UIの構築、機能の追加、バグ修正に
役立ちます。
修正前の画面状態を残したままで、
エミュレータ、シミュレータ、および iOSと
Androidのハードウェアでも、
1秒未満でリロード/更新反映されます。
Flutter 公式サイト https://flutter.dev/
表現力豊かで美麗なUI
7
● Expressive, beautiful UIs
Flutterには、ユーザーを魅惑する、表現力
豊かなウイジェットが組み込まれていま
す。
マテリアルデザイン(美麗)、クパチーノ(iOS
フレーバーを提供)、リッチモーションAPI、
スムーズで自然なスクロール、プラット
フォームごとに雰囲気を変える ウィジェット
があります。
Flutter 公式サイト https://flutter.dev/
ネイティブパフォーマンス
8
● Native Performance
Flutterのウィジェットには、スクロール、ナ
ビゲーション、アイコン、フォントなど、プ
ラットフォームの重要な違いがすべて組み
込まれています。
これにより、iOSとAndroidの両方で、
ネイティブパフォーマンスが発揮されます。
Flutter 公式サイト https://flutter.dev/
Dart言語による開発
9
Dart言語 公式サイト https://dart.dev/
● Dart Language
アプリは、Dart 言語で開発します。
Dart の言語は、
JavaScript の知見をベースに、
より良いアプリ開発や OOP のため、
Google が新たに設計した言語です。
Dart 言語 公式資料
● Tutorials
https://dart.dev/tutorials
● Effective Dart
https://dart.dev/guides/language/effective-dart
● A tour of the Dart language
https://dart.dev/guides/language/language-tour
● API Reference
https://api.dart.dev/stable/2.9.0/index.html
10
おまけ
Dart 言語は、
クライアント開発だけでなく、サーバ開発にも使えます。
● Dartでサーバレスサービス
https://www.slideshare.net/cch-robo/dart-237637482
11
Dart言語の歴史
WIKIPEDIA - Dart (programming language) より
Dart 言語は、2010/10 にプロジェクトが立ち上がり、
2013/11 に Dart 1.0 安定版がリリースされました。
12
Dart 1.0: A stable SDK for structured web apps (2013/11/14)
https://news.dartlang.org/2013/11/dart-10-stable-sdk-for-structured-web.html
GOTO Conference 2011/10/10-12 Opening Keynote Presentation 紹介
"Dart, a new programming language for structured web programming"
http://gotocon.com/aarhus-2011/presentation/Opening%20Keynote:%20Dart,%20a%20new%20programming%20l
anguage%20for%20structured%20web%20programming
Dart は、JavaScript の知見をベースとした
Web開発のための新しい言語として誕生
13
http://gotocon.com/dl/goto-aarhus-2011/slides/GiladBracha_and_LarsBak_OpeningKeynoteDartANe
wProgrammingLanguageForStructuredWebProgramming.pdf
HISTORY BEHIND DART
• After several years working on V8 for Chrome
• Last year, Kasper Lund & I experimented with Spot
 • a new simple language for the web
 • based on the experiences from JavaScript
• Spot was the prelude for the Dart project
SO WHAT IS DART?
• A simple and unsurprising OO programming language
 • Class-based single inheritance with interfaces
 • Optional static types
 • Real lexical scoping
 • Single-threaded
 • Familiar syntax
Keynote Presentation Slide より
Dart 言語の大きな特徴として、オプションですが静的型付(実際は静的チェッカ
⇒参考元)をサポートし、プログラム構造を明示できるようインターフェースを使用した単
一継承クラスベースであることが掲げられています。
JavaScript の困ったところは、バッサリ切り捨て
14
Dart FAQ
Q. What does Google think of TypeScript?
https://dart.dev/faq#q-what-does-google-think-of-typescript
TypeScript maintains backwards compatability with JavaScript,
whereas Dart purposely made a break from certain parts of JavaScript’s syntax
and semantics in order to eradicate large classes of bugs and to improve performance.
TypeScriptは、JavaScriptとの後方互換性を維持しますが、
Dartは意図的にJavaScriptの特定の構文とセマンティクス(意味解釈)を壊し、
バグの大元を取り去り、パフォーマンスを向上させています。
JavaScript に構文が似ていても挙動は異なる
15
DartPad
https://dartpad.dev/
JS : Firefox ウェブ開発 の ウェブコンソール結果
'use strict';
var num = 101;
var str = '101';
console.log(num == str); // ⇒ true
console.log(num === str); // ⇒ false
Dart : DartPad での実行結果
void main() {
var num = 101;
var str = '101';
print(num == str); // ⇒ false
}
Dart は JavaScript と構文が似ていますが、暗黙の型変換を切り捨てています。
意図的にセマンティクスを変更しているので、同じようなコードであっても
別物と考える必要があります。
Dart 2 から大規模変革開始
型システムが強化され 静的型付言語 となりました。
Webだけでなく、モバイルを含めたクライアント開発の
(現在ではデスクトップ含むマルチプラットフォーム開発の)
言語に強化されています。
16
Announcing Dart 2: Optimized for Client-Side Development (2018/02/23)
https://medium.com/dartlang/announcing-dart-2-80ba01f43b6
The Dart type system
https://dart.dev/guides/language/type-system
Announcing Dart 2 Stable and the Dart Web Platform (2018/08/08)
https://medium.com/dartlang/dart-2-stable-and-the-dart-web-platform-3775d5f8eac7
● 2.0 sound type system ⇒ 静的型解決対応 (1.xコードからの移行必須化 )
● 2.3 spread operator の追加
collection if と collection for の追加
● 2.7 extension methods ⇒ 拡張メソッド をサポート
● 2.8 来たるべき null safety ⇒ null 安全 への布石
今後の進化は?
17
Dart language evolution
https://dart.dev/guides/language/evolution
Dart 2.0からの 進化の抜粋
18
Dart プロパティアクセス
var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => alert('Confirmed!'));
Dart カスケード表記
querySelector('#confirm') // Get an object.
..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => alert('Confirmed!'));
spread operator の前に、
cascade notation ⇒ カスケード表記を説明
Cascade notation
https://dart.dev/guides/language/language-tour#cascade-notation-
カスケード表記⇒ .. は、
同じオブジェクトのプロパティやメソッド指定する構文です。
これにより各メンバーへの連鎖的な設定が記述できます。
(.. の実態は演算子でなく、Dart 構文です)
19
Dart スプレッド演算子
var list = [1, 2, 3];
var list2 = [0, ...list];
assert(list2.length == 4);
Dart スプレッド演算子(null認識表記)
var list;
var list2 = [0, ...?list];
assert(list2.length == 1);
spread operator ⇒ スプレッド演算子は、
コレクションへの操作を 各要素への操作に展開します。
spread operator
https://dart.dev/guides/language/language-tour#spread-operator
スプレッド演算子⇒ … は、
... 右辺のコレクションに対する操作を、
その各要素への操作として展開します。
これによりリスト全要素の別リストへの挿入も手軽に記述できます。
20
Dart コレクション if
var nav = [
'Home',
'Furniture',
'Plants',
if (promoActive) 'Outlet' // true 時のみ挿入
];
Dart コレクション for
var listOfInts = [1, 2, 3];
var listOfStrings = [
'#0',
for (var i in listOfInts) '#$i'
];
// listOfStrings ⇒ ['#0','#1','#2','#3']
collection if / collection for は、
コレクションへの 条件 / 繰返 指定付きの要素挿入です。
collection if / collection for
https://dart.dev/guides/language/language-tour#collection-operators
コレクション if と コレクション for により、、
コレクションへの要素挿入処理の記述が手軽になります。
21
Dart 拡張メソッド
extension CountService on String {
int countExclamations() =>
this.length - this.replaceAll("!","").length;
}
void main() {
print("Hello, world!!!".countExclamations());
// 3 が表示される。
}
【参考】Kotlin 拡張関数
fun String.countExclamations():
Int = this.length - this.replace("!","").length
fun main() {
println("Hello, world!!!".countExclamations())
// 3 が表示される。
}
extension methods ⇒ 拡張メソッドは、
既存クラスにメソッドやプロパティを追加し(たように見せ)ます。
Extension methods
https://dart.dev/guides/language/extension-methods
null 安全に移行すると、
既存の変数宣言は、null 不可型 の変数宣言になります。
null も許すなら、null 許容型 の変数宣言への変更必須です。
null 不可型変数には、nullが設定されなことが保証されますが、
null 安全は、まだテクニカルプレビューなので製品版には使わないで!
ここでは表記単純化のため non-null や non-nullable を null 不可、
nullable を null許容 …と共通意訳していることに留意ください。
22
Understanding null safety
https://dart.dev/null-safety/understanding-null-safety
Sound null safety
https://dart.dev/null-safety
null safety ⇒ null 安全
23
Dart の Null 安全 : DartPad with null safety での実行結果
void main() {
String? nullableStr = null; // OK! (null 許容型の String として宣言)
int nonNullNum = 100; // OK! (null 不可型の int として宣言)
int? nullableNum = null; // OK! (null 許容型の int として宣言)
nonNullNum = nullableNum; // Type mismatch: inferred type is Int? but Int was expected
String nonNullStr = null; // Null can not be a value of a non-null type String
}
DartPad with null safety
https://nullsafety.dartpad.dev/
null safety ⇒ null 安全では、
型宣言? で null 許容型、なければ常に null 不可型になる。
24
class Sample {
// 初回アクセスされるまでに初期化されていれば良い、 null 不可型宣言フィールド
late String lateStr;
void init() { print("late -> "); lateStr = "Hello"; }
}
void main() {
Sample sample = Sample();
sample.init();
print("lateStr=${sample.lateStr}"); // late -> lateStr=Hello
}
null safety ⇒ null 不可なフィールドは、
late 型宣言で 遅延設定フィールド に修正する。
late を付けて宣言しないとエラーになる。
Error: Field 'lateStr' should be initialized
because its type 'String' doesn't allow null.
String lateStr;
^^^^^^^
25
null safety ⇒ null 安全では、
null 不可なオプション引数に、初期値が必須になる。
void present(
String name, {String color}) {
print('I send you a $color $name.');
}
Error: Optional parameter 'color' should
have a default value because its type
'String' doesn't allow null.
String name, {String color}) {
^^^^^
void main() {
present('rose', color:'red');
}
void present(
String name, {String color='white'}) {
print('I send you a $color $name.');
// I send you a red rose. が表示される。
}
オプション引数に、初期値があるとき。 オプション引数に、初期値がないとき。
26
Flutter Day Livestream | Session 3: Dart
https://www.youtube.com/watch?v=ZxSyZHq8gUg&feature=youtu.be&t=1618
null safety ⇒ null 安全に移行するには、
既存ソースからの移行作業が必須になります。
nnbd_migration 0.1.0
https://pub.dev/packages/nnbd_migration
null 安全は、魅力的ですが、
既存のコードやライブラリは、
移行作業(コード修正)が必須です
このため Dart チームは、
移行ツールを提供しています。
Note: the null safety migration tooling is in an early
state and may have bugs and other issues.
For best results, use SDK version 2.9.0-10.0.dev or higher.
27
Kotlin Playground
https://play.kotlinlang.org/
【参考】Kotlin の Null 安全 : Kotln Playground での実行結果
fun main() {
var nullableNum : Int? = null // OK! (Null 許容型の Int として宣言)
var nonNullNum : Int = 100 // OK! (Null 不可型の Int として宣言)
var nullableStr : String? = null // OK! (Null 許容型の String として宣言)
nonNullNum = nullableNum // Type mismatch: inferred type is Int? but Int was expected
var nonNullStr : String = null // Null can not be a value of a non-null type String
}
【参考】 Kotlin の Null Safety ⇒ Null 安全も、
型宣言? であれば Null 許容型、なければ常に Null 不可型
28
class Sample {
// 初回アクセスされるまでに初期化されていれば良い、 Null 不可型宣言フィールド
lateinit var lateStr : String
// 初回アクセス時に初期化の移譲関数が実行される、 Null 不可型宣言フィールド
val lazyNum : Int by lazy { print("lazy -> "); 100 }
fun init() { print("late -> "); lateStr = "Hello" }
}
fun main(args: Array<String>) {
val sample = Sample(); sample.init()
println("lateStr=${sample.lateStr}") // late -> lateStr=Hello
println("lazyNum=${sample.lazyNum}") // lazy -> lazyNum=100
}
【参考】 Kotlin の Null 安全な、遅延設定フィールドは、
lateinit か lazy 移譲関数を指定する。
29
Flutter Day Livestream | Session 3: Dart
https://www.youtube.com/watch?v=ZxSyZHq8gUg&feature=youtu.be&t=2650
#AskFlutter #FlutterDay 回答より
rich enum types や sealed classes
導入について、何度か検討したが、
現時点では約束できないそうです。
今後の進化は?
30
Are there any sealed classes alternatives in Dart 2.0?
https://stackoverflow.com/questions/54317000/are-there-any-sealed-classes-alternatives-in-dart-2-0
【補足】 Sealed Class は、
完全ではありませんが擬似コードは作れます。
【参考】Kotlin シールドクラス例
sealed class MyState {
data class Success(val data: List<MyObject>) : MyState()
data class Error(val error: String) : MyState()
}
シールドクラスは、継承可能な範囲(派生先)を制限するクラス
これにより派生物ごとの処理制御が保証可能になります。
stack overflow に Dartでの擬似コードの回答例がありました。
31
Algebraic Data Types (ADTs, Sealed Classes, Enum with associated values)
https://github.com/dart-lang/language/issues/349
Dart での擬似コード回答例
class MyState {
MyState._();
factory MyState.success(String foo) = MySuccessState;
factory MyState.error(String foo) = MyErrorState;
}
class MyErrorState extends MyState {
MyErrorState(this.msg): super._();
final String msg;
}
class MySuccessState extends MyState {
MySuccessState(this.value): super._();
final String value;
}
擬似コードでも、
想定を満たしますが、
Kotlin の
シールドクラスは、
定義されたファイル以外
に、指定されたクラスの
他の実装がないことまで
保証できます。
dart-lang に ISSUE は立ってます。
Flutterアプリのプログラム
32
● 画面もロジックもDartで作成
Flutter アプリは、画面レイアウトや UI のみ
ならず JSONフェッチなどの機能も
全てコードで作成します。
● Flutter for Web
Flutter は、モバイル開発だけでなく、
ベータ版ですが Web アプリも作れます。
画面レイアウトも UI も機能やロジックも、
Flutter は全て Dart コード で作成するという
プログラムコードは、どんなものでしょう。
Flutterアプリのプログラム開発例
東京都 新型コロナウイルス感染症 対策サイト の
最新検査状況を表示する Web アプリを作ってみました。
33
ホスティングしていないので、
ローカルサーバで動作させて
います。
この画面作成とHTMLスクレイピングの
全コードを紹介します。
Flutter for Web でのプログラミング
アプリを作るためのプログラミングは、
どのようなものなのか紹介します。
まずは、画面作成から。
34
画面作成の全ソース(1/4)
35
import 'package:flutter/material.dart';
import 'tokyo_stop_covid19.dart';
PositiveSituation jsonModel;
Future<void> main() async {
jsonModel = await TokyoStopCovid19.createPositiveSituation();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyPage(),
);
}
}
class MyPage extends StatelessWidget {
const MyPage({Key key}) : super(key: key);
Widget _customText(String label, {double fontSize = 12.0,
FontWeight fontWeight = FontWeight.normal}) {
return Expanded(
child: Container(
alignment: Alignment.center,
margin: const EdgeInsets.all(4.0),
child: Text('$label', style: TextStyle(fontSize:
fontSize, fontWeight: fontWeight))
),
);
}
画面を作る my_app.dart の全ソースは、
4ページ分しかありません。
この後、スライドのダウンロード先を紹介します。
画面作成の全ソース(2/4)
36
@override
Widget build(BuildContext context) {
print('jsonModel=$jsonModel');
return Scaffold(
backgroundColor: Colors.white70,
body: Center(
child: Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black54,
spreadRadius: 1.0,
blurRadius: 10.0,
offset: Offset(10, 10),
),
],
),
child:Card(
color: Colors.white,
child: Container(
上の画面は、
この4ページ分のコードで仕上がります。
画面作成の全ソース(3/4)
37
child:Card(
color: Colors.white,
child: Container(
width: 500.0,
margin: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 0.0),
child:Column(
mainAxisSize: MainAxisSize.min,
children:[
Container(
alignment: Alignment.center,
margin: const EdgeInsets.all(4.0),
child: Text('東京都 検査陽性者の状況', style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.w600)),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
_customText('累計'),
_customText('入院中'),
_customText('軽症〜中等症'),
_customText('重症'),
_customText('死亡'),
_customText('退院'),
],
),
Divider(height: 14.0, color: Colors.black12),
Flutter には、
Material Design に準拠した
Widget と呼ばれる UI やレイアウトのコン
ポーネント・パーツが
たくさん用意されています。
画面作成の全ソース(4/4)
38
Divider(height: 14.0, color: Colors.black12),
Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
_customText(jsonModel?.cumulative.toString() ?? '0'),
_customText(jsonModel?.hospitalized.toString() ?? '0'),
_customText(jsonModel?.mild2moderate.toString() ?? '0'),
_customText(jsonModel?.severe.toString() ?? '0'),
_customText(jsonModel?.death.toString() ?? '0'),
_customText(jsonModel?.discharge.toString() ?? '0'),
],
),
Container(
alignment: Alignment.centerRight,
margin: const EdgeInsets.all(4.0),
child: Text('${jsonModel?.updateString() ?? DateTime.now()} 更新', style: TextStyle(fontSize: 14.0)),
),
],
),
),
),
),
),
);
}
}
_customText() (1ページめの定義参照) のように、
特定UIをこなしてくれる、独自のコンポーネントを
プログラムで定義することもできます。
Flutter for Web でのプログラミング
サンプルの Webアプリでは、最新の検査状況を
東京都 新型コロナウイルス感染症 対策サイトページから
スクレイピングして JSON データに変換しています。
続いて、HTML スクレイピング。
39
スクレイピングの全ソース(1/4)
40
import 'dart:convert'; // ignore:directives_ordering
import 'package:http/http.dart' as http;
/// 東京都 都内の最新感染動向 を表すクラス
class TokyoStopCovid19 {
/// HTML スクレイピングによる 検査陽性者状況 JSON 取得
static Future<Map<String, dynamic>> scrapingPositiveSituation() async {
http.Response response;
// 東京都 都内の最新幹線動向 サイト
const String host = ‘stopcovid19.metoro.tokyo.lg.jp';
const String path = '/';
const String url = 'https://' + host + path;
print('beore scrapingPositiveSituation() => request.url=$url');
response = await http.get(url);
print('after scrapingPositiveSituation() => request.url=$url');
if (response.statusCode != 200) {
throw new StateError('HTTP Response status code is ${response.statusCode}');
}
// 都内の最新幹線動向 ページの HTML body テキスト
final String htmlBody = utf8.decode(response.bodyBytes);
// 検査要請者の状況ブロックのみ HTMLテキスト抽出
東京都のページから、
最新の検査状況をスクレイピングする
tokyo_stop_covid19.dart の
全ソースは4ページ分だけです。
https://stopcovid19.metro.tokyo.lg.jp/ から、
HTML テキストを直接取得して、
スクレイピングしています。
スクレイピングの全ソース(2/4)
41
// 都内の最新幹線動向 ページの HTML body テキスト
final String htmlBody = utf8.decode(response.bodyBytes);
// 検査要請者の状況ブロックのみ HTMLテキスト抽出
bool isExtracting = false;
final String extracts = htmlBody.split(RegExp('n')).where(
(String line) {
if (line.contains(RegExp('検査陽性者の状況'))) isExtracting = true;
if (line.contains(RegExp('検査実施状況'))) isExtracting = false;
return isExtracting;
}
).toList().join();
// 種別〜人数ブロックのみ HTMLテキスト抽出
isExtracting = false;
List<String> contents = extracts.split(RegExp('> ?<')).where(
(String line) {
if (line.contains(RegExp('class="content_1gFZ-"'))) isExtracting = true;
if (line.contains(RegExp('class="unit_25C4Z"'))) isExtracting = false;
return isExtracting;
}
).join().split(RegExp('div class="content_1gFZ-"'));
// 更新日付ブロックのみ HTMLテキスト抽出
isExtracting = false;
String datetime = extracts.split(RegExp('> ?<')).where((String line) {
return line.contains(RegExp('time datetime='));
}).join();
文字が小さくて読めないと思いますので、
この後、スライドのダウンロード先を紹介します。
Dart 言語は、
JavaScript(ES2015)に似ています。
class や async / await、アロー関数、
コレクションのストリーム処理などが
使えます。
スクレイピングの全ソース(3/4)
42
// 種別〜人数+更新日付ブロックのみ HTMLテキスト
contents.add(datetime);
// 抽出 HTML テキストから JSON を生成する。
final Map<String, dynamic> json = contents.map<Map<String,dynamic>>(
(String content) {
Map<String, dynamic> el;
if (content.contains(RegExp('累計'))) el = {'cumulative': _extractNum(content)};
if (content.contains(RegExp('入院'))) el = {'hospitalized': _extractNum(content)};
if (content.contains(RegExp('軽症'))) el = {'mild2moderate': _extractNum(content)};
if (content.contains(RegExp('重症'))) el = {'severe': _extractNum(content)};
if (content.contains(RegExp('死亡'))) el = {'death': _extractNum(content)};
if (content.contains(RegExp('退院'))) el = {'discharge': _extractNum(content)};
if (content.contains(RegExp('更新'))) el = {'updatetime': _extractDatetime(content)};
return el;
}
).reduce(
(Map<String, dynamic> prev, Map<String, dynamic> curr) {
curr.addAll(prev ?? {});
return curr;
}
);
print('json=$json');
return json;
}
/// 数値抽出関数
スクレイピングした HTML テキストから、
JSON データ ⇒ Map<String, dynamic> に
変換しています。
スクレイピングの全ソース(4/4)
43
/// 数値抽出関数
static int _extractNum(String content) {
final String num = content
.replaceFirst(RegExp('^[^0-9]*'), '')
.replaceFirst(RegExp('[^0-9]*$'), '');
return int.parse(num);
}
/// 日付抽出関数
static DateTime _extractDatetime(String content) {
final String date = content
.replaceFirst(RegExp('^time datetime="'), '')
.replaceFirst(RegExp('".*$'), '');
return DateTime.parse(date);
}
}
こちらは、内部で利用する、
ユーティリティ関数となります。
全体的に JavaScript に似かよったプログラムになっています。
スクレイピングの補足
44
検査陽性者の状況</h3> </div> <div class="DataView-Description"></div>
<div><p class="note_3ycFr">(注)チャーター機帰国者、クルーズ船乗客等は含まれていない
</p></div> <div class="DataView-CardText"> <ul aria-label="検査陽性者の状況"
class="container_37WEO"><li class="box_2dey9 parent_23pyN confirmed_P-yFc">
<div class="pillar_F62Yl"><div class="content_1gFZ-"><span>陽性者数<br>(累計)</span>
<span><strong>154</strong> <span class="unit_25C4Z">人</span></span></div></div>
<ul class="group_1ksdS"><li class="box_2dey9 parent_23pyN hospitalized_3w7PT">
<div class="pillar_F62Yl"><div class="content_1gFZ-"><span>入院中</span>
<span><strong>119</strong> <span class="unit_25C4Z">人</span></span></div></div>
<ul class="group_1ksdS"><li class="box_2dey9 minor_1RUXC"><div class="pillar_F62Yl">
〜 省略 〜
<li class="box_2dey9 recovered_JzYjB"><div class="pillar_F62Yl"><div
class="content_1gFZ-"><span>退院</span> <span><strong>31</strong>
<span class="unit_25C4Z">人</span></span>
</div></div></li></ul></li></ul></div> <div class="DataView-Description"></div>
〜 省略 〜
<div class="DataView-Footer"><div class="Footer-Left"><div><!----></div> <div>
<a href="/cards/details-of-confirmed-cases" class="Permalink">
<time datetime="2020-03-23T21:15:00">2020/03/23 21:15 更新</time></a></div></div>
<div class="Footer-Right"><button class="DataView-Share-Opener">
<svg width="14" height="16" viewBox="0 0 14 16" fill="none"
xmlns="http://www.w3.org/2000/svg"
role="img" aria-label="検査陽性者の状況のグラフをシェア">
〜 省略 〜
<div class="DataCard col-md-6 col-12" data-v-59bfe8e7>
<div class="DataView v-card v-sheet theme--light"><div class="DataView-Inner">
<div class="DataView-Header"><h3 class="DataView-Title">
検査陽性者の状況 部から抽出した
HTML テキスト
<div class="content_1gFZ-">
<span>入院中</span>
<span>
<strong>119</strong>
<span class="unit_25C4Z">人</span>
</span>
</div>
3月23日のコンテンツでは、
種別ごとの DIV タグには、
class="content_1gFZ-" が割り当てられ、
人数を表す SPAN タグには、
class="unit_25C4Z" が割り当てられている
…ことを利用して抽出しています。
Flutter での Webアプリ開発
画面のレイアウトや UI を全てコードで記述することや
Dart言語は、JavaScript とあまり変わらないことを
確認いただけましたでしょうか。  
Flutter 公式資料
Flutter for web developers ⇒ CSS や HTML と Flutter コードの違い説明
https://flutter.dev/docs/get-started/flutter-for/web-devs
Building a web application with Flutter ⇒ Flutter での Webアプリ作成手順
https://flutter.dev/docs/get-started/web
45
お詫び
dart言語は、最終的に JavaScript に変換されるため、
外部サイト(東京都サイト)からの HTML テキスト取得は、
サイトをまたがる CORS ポリシー違反になります。
このためサンプル Web アプリは、
ブラウザの CORSポリシーを無効 にしなければ、
実行できません。
46
CORSポリシーを一時的に無効にする
● CORSポリシーを無効にした Chrome を起動する。
Webアプリから外部サイトのリソース (JSON情報など)を取得する必用がある場合は、
起動オプションで CORS ポリシーを無効にした Chorome を開き、それで実行させます。
【参考】Run Chrome browser without CORS ⇒ https://alfilatov.com/posts/run-chrome-without-cors/
この方法は、あくまでデバッグなどでの一時的な対処です。
本来は、アクセスするサーバ側で Access-Control-Allow-Origin などの設定をするのが正式です。
CORSポリシーが無効化されるのは、上記で起動した Chrome ウィンドウだけなことに注意! 47
# MacOS で、セキュリティポリシーを無効にした Chrome を起動させます。(下記は一行コマンド)
$ open -n -a /Applications/Google Chrome.app/Contents/MacOS/Google Chrome --args
--user-data-dir="/tmp/chrome_dev_test" --disable-web-security
# Windows 10で、セキュリティポリシーを無効にした Chrome を起動。(下記は一行コマンド)
> "C:Program Files (x86)GoogleChromeApplicationchrome.exe"
--disable-web-security --disable-gpu --user-data-dir=~/chromeTemp
# Linux で、セキュリティポリシーを無効にした Chrome を起動。(下記は一行コマンド)
$ google-chrome --user-data-dir="/tmp/chrome_dev_test" --disable-web-security
48
検証ツールでコンソールを確認すれば、
画面表示時にスクレイピングが行われて、
検査状況より JSON データを作っていることが
確認できます。
むすび
Flutter って なんだか良さそう
…と思っていただけましたでしょうか。
GDG Kyoto は、
Google テクノロジーに興味のある 初心者から 専門家の方に、
開発者同士の交流や 新しいスキルへの学びを支援するコミュニティです。
Flutter 開発についても取り組んでいますので、お気軽に参加ください ❤
49
50
ご清聴、
ありがとうございました。
情報修正があれば更新します
最新版スライドは こちらから

More Related Content

What's hot

C#や.NET Frameworkがやっていること
C#や.NET FrameworkがやっていることC#や.NET Frameworkがやっていること
C#や.NET Frameworkがやっていること信之 岩永
 
エラーハンドリング
エラーハンドリングエラーハンドリング
エラーハンドリング道化師 堂華
 
Boost.勉強会#19東京 Effective Modern C++とC++ Core Guidelines
Boost.勉強会#19東京 Effective Modern C++とC++ Core GuidelinesBoost.勉強会#19東京 Effective Modern C++とC++ Core Guidelines
Boost.勉強会#19東京 Effective Modern C++とC++ Core GuidelinesShintarou Okada
 
C# コーディングガイドライン 2013/02/26
C# コーディングガイドライン 2013/02/26C# コーディングガイドライン 2013/02/26
C# コーディングガイドライン 2013/02/26Yoshihisa Ozaki
 
.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#信之 岩永
 
Try_to_writecode_practicaltest #atest_hack
Try_to_writecode_practicaltest #atest_hackTry_to_writecode_practicaltest #atest_hack
Try_to_writecode_practicaltest #atest_hackkimukou_26 Kimukou
 
Code Contracts の紹介
Code Contracts の紹介Code Contracts の紹介
Code Contracts の紹介ゆぽ
 
はこだてIKA 第4回勉強会 単体テスト
はこだてIKA 第4回勉強会 単体テストはこだてIKA 第4回勉強会 単体テスト
はこだてIKA 第4回勉強会 単体テストSeiji KOMATSU
 
オブジェクト指向できていますか?
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?Moriharu Ohzu
 
第4回勉強会 単体テストのすすめ
第4回勉強会 単体テストのすすめ第4回勉強会 単体テストのすすめ
第4回勉強会 単体テストのすすめhakoika-itwg
 
C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)信之 岩永
 
Flutter のリアクティブ戦略 set state 〜 redux まで
Flutter のリアクティブ戦略 set state 〜 redux までFlutter のリアクティブ戦略 set state 〜 redux まで
Flutter のリアクティブ戦略 set state 〜 redux までcch-robo
 
C#言語機能の作り方
C#言語機能の作り方C#言語機能の作り方
C#言語機能の作り方信之 岩永
 
C# から java へのプログラム移植で体験したtddの効果は?
C# から java へのプログラム移植で体験したtddの効果は?C# から java へのプログラム移植で体験したtddの効果は?
C# から java へのプログラム移植で体験したtddの効果は?Shinichi Hirauchi
 
111008 silverlight square_datavalidation
111008 silverlight square_datavalidation111008 silverlight square_datavalidation
111008 silverlight square_datavalidationTakayoshi Tanaka
 
Swift2 の新機能 Protocol Extension
Swift2 の新機能 Protocol ExtensionSwift2 の新機能 Protocol Extension
Swift2 の新機能 Protocol ExtensionYuichi Adachi
 
JavaDayTokyo2015 [3-1]
JavaDayTokyo2015 [3-1]JavaDayTokyo2015 [3-1]
JavaDayTokyo2015 [3-1]Kenji Kazumura
 
C# 8.0 null許容参照型
C# 8.0 null許容参照型C# 8.0 null許容参照型
C# 8.0 null許容参照型信之 岩永
 

What's hot (20)

C#や.NET Frameworkがやっていること
C#や.NET FrameworkがやっていることC#や.NET Frameworkがやっていること
C#や.NET Frameworkがやっていること
 
エラーハンドリング
エラーハンドリングエラーハンドリング
エラーハンドリング
 
Boost.勉強会#19東京 Effective Modern C++とC++ Core Guidelines
Boost.勉強会#19東京 Effective Modern C++とC++ Core GuidelinesBoost.勉強会#19東京 Effective Modern C++とC++ Core Guidelines
Boost.勉強会#19東京 Effective Modern C++とC++ Core Guidelines
 
C# コーディングガイドライン 2013/02/26
C# コーディングガイドライン 2013/02/26C# コーディングガイドライン 2013/02/26
C# コーディングガイドライン 2013/02/26
 
C# 9.0 / .NET 5.0
C# 9.0 / .NET 5.0C# 9.0 / .NET 5.0
C# 9.0 / .NET 5.0
 
.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#
 
Try_to_writecode_practicaltest #atest_hack
Try_to_writecode_practicaltest #atest_hackTry_to_writecode_practicaltest #atest_hack
Try_to_writecode_practicaltest #atest_hack
 
Code Contracts の紹介
Code Contracts の紹介Code Contracts の紹介
Code Contracts の紹介
 
C#の書き方
C#の書き方C#の書き方
C#の書き方
 
はこだてIKA 第4回勉強会 単体テスト
はこだてIKA 第4回勉強会 単体テストはこだてIKA 第4回勉強会 単体テスト
はこだてIKA 第4回勉強会 単体テスト
 
オブジェクト指向できていますか?
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?
 
第4回勉強会 単体テストのすすめ
第4回勉強会 単体テストのすすめ第4回勉強会 単体テストのすすめ
第4回勉強会 単体テストのすすめ
 
C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)
 
Flutter のリアクティブ戦略 set state 〜 redux まで
Flutter のリアクティブ戦略 set state 〜 redux までFlutter のリアクティブ戦略 set state 〜 redux まで
Flutter のリアクティブ戦略 set state 〜 redux まで
 
C#言語機能の作り方
C#言語機能の作り方C#言語機能の作り方
C#言語機能の作り方
 
C# から java へのプログラム移植で体験したtddの効果は?
C# から java へのプログラム移植で体験したtddの効果は?C# から java へのプログラム移植で体験したtddの効果は?
C# から java へのプログラム移植で体験したtddの効果は?
 
111008 silverlight square_datavalidation
111008 silverlight square_datavalidation111008 silverlight square_datavalidation
111008 silverlight square_datavalidation
 
Swift2 の新機能 Protocol Extension
Swift2 の新機能 Protocol ExtensionSwift2 の新機能 Protocol Extension
Swift2 の新機能 Protocol Extension
 
JavaDayTokyo2015 [3-1]
JavaDayTokyo2015 [3-1]JavaDayTokyo2015 [3-1]
JavaDayTokyo2015 [3-1]
 
C# 8.0 null許容参照型
C# 8.0 null許容参照型C# 8.0 null許容参照型
C# 8.0 null許容参照型
 

Similar to Flutterを体験してみませんか

規格書で読むC++11のスレッド
規格書で読むC++11のスレッド規格書で読むC++11のスレッド
規格書で読むC++11のスレッドKohsuke Yuasa
 
Inside frogc in Dart
Inside frogc in DartInside frogc in Dart
Inside frogc in DartGoro Fuji
 
Groovy Bootcamp 2015 by JGGUG
Groovy Bootcamp 2015 by JGGUGGroovy Bootcamp 2015 by JGGUG
Groovy Bootcamp 2015 by JGGUGUehara Junji
 
DTrace for biginners part(2)
DTrace for biginners part(2)DTrace for biginners part(2)
DTrace for biginners part(2)Shoji Haraguchi
 
15分でわかった気になるdart
15分でわかった気になるdart15分でわかった気になるdart
15分でわかった気になるdartSatoshi KOBAYASHI
 
Pact言語によるセキュアなスマートコントラクト開発
Pact言語によるセキュアなスマートコントラクト開発Pact言語によるセキュアなスマートコントラクト開発
Pact言語によるセキュアなスマートコントラクト開発Nagato Kasaki
 
TypeScript と Visual Studio Code
TypeScript と Visual Studio CodeTypeScript と Visual Studio Code
TypeScript と Visual Studio CodeAkira Inoue
 
復習も兼ねて!C#6.0-7.0
復習も兼ねて!C#6.0-7.0復習も兼ねて!C#6.0-7.0
復習も兼ねて!C#6.0-7.0Yuta Matsumura
 
Boost.Flyweight
Boost.FlyweightBoost.Flyweight
Boost.Flyweightgintenlabo
 
Introduce Groovy 2.3 trait
Introduce Groovy 2.3 trait Introduce Groovy 2.3 trait
Introduce Groovy 2.3 trait Uehara Junji
 
今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 TipsTakaaki Suzuki
 
わんくま同盟大阪勉強会#61
わんくま同盟大阪勉強会#61わんくま同盟大阪勉強会#61
わんくま同盟大阪勉強会#61TATSUYA HAYAMIZU
 
TypeScript ファーストステップ (Rev.2) ~ Any browser. Any host. Any OS. Open Source. ~
TypeScript ファーストステップ (Rev.2) ~ Any browser. Any host. Any OS. Open Source. ~TypeScript ファーストステップ (Rev.2) ~ Any browser. Any host. Any OS. Open Source. ~
TypeScript ファーストステップ (Rev.2) ~ Any browser. Any host. Any OS. Open Source. ~Akira Inoue
 
DartPad+CodePenで、Flutterを体験してみよう
DartPad+CodePenで、Flutterを体験してみようDartPad+CodePenで、Flutterを体験してみよう
DartPad+CodePenで、Flutterを体験してみようcch-robo
 
GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法博文 斉藤
 
DEV-011_TypeScript ~Any browser. Any host. Any OS. Open Source~
DEV-011_TypeScript ~Any browser. Any host. Any OS. Open Source~DEV-011_TypeScript ~Any browser. Any host. Any OS. Open Source~
DEV-011_TypeScript ~Any browser. Any host. Any OS. Open Source~decode2016
 
Visual C++で使えるC++11
Visual C++で使えるC++11Visual C++で使えるC++11
Visual C++で使えるC++11nekko1119
 

Similar to Flutterを体験してみませんか (20)

Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
 
規格書で読むC++11のスレッド
規格書で読むC++11のスレッド規格書で読むC++11のスレッド
規格書で読むC++11のスレッド
 
Inside frogc in Dart
Inside frogc in DartInside frogc in Dart
Inside frogc in Dart
 
Groovy Bootcamp 2015 by JGGUG
Groovy Bootcamp 2015 by JGGUGGroovy Bootcamp 2015 by JGGUG
Groovy Bootcamp 2015 by JGGUG
 
DTrace for biginners part(2)
DTrace for biginners part(2)DTrace for biginners part(2)
DTrace for biginners part(2)
 
15分でわかった気になるdart
15分でわかった気になるdart15分でわかった気になるdart
15分でわかった気になるdart
 
Pact言語によるセキュアなスマートコントラクト開発
Pact言語によるセキュアなスマートコントラクト開発Pact言語によるセキュアなスマートコントラクト開発
Pact言語によるセキュアなスマートコントラクト開発
 
ATN No.2 Scala事始め
ATN No.2 Scala事始めATN No.2 Scala事始め
ATN No.2 Scala事始め
 
TypeScript と Visual Studio Code
TypeScript と Visual Studio CodeTypeScript と Visual Studio Code
TypeScript と Visual Studio Code
 
復習も兼ねて!C#6.0-7.0
復習も兼ねて!C#6.0-7.0復習も兼ねて!C#6.0-7.0
復習も兼ねて!C#6.0-7.0
 
Boost.Flyweight
Boost.FlyweightBoost.Flyweight
Boost.Flyweight
 
Introduce Groovy 2.3 trait
Introduce Groovy 2.3 trait Introduce Groovy 2.3 trait
Introduce Groovy 2.3 trait
 
Boost Fusion Library
Boost Fusion LibraryBoost Fusion Library
Boost Fusion Library
 
今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips
 
わんくま同盟大阪勉強会#61
わんくま同盟大阪勉強会#61わんくま同盟大阪勉強会#61
わんくま同盟大阪勉強会#61
 
TypeScript ファーストステップ (Rev.2) ~ Any browser. Any host. Any OS. Open Source. ~
TypeScript ファーストステップ (Rev.2) ~ Any browser. Any host. Any OS. Open Source. ~TypeScript ファーストステップ (Rev.2) ~ Any browser. Any host. Any OS. Open Source. ~
TypeScript ファーストステップ (Rev.2) ~ Any browser. Any host. Any OS. Open Source. ~
 
DartPad+CodePenで、Flutterを体験してみよう
DartPad+CodePenで、Flutterを体験してみようDartPad+CodePenで、Flutterを体験してみよう
DartPad+CodePenで、Flutterを体験してみよう
 
GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法
 
DEV-011_TypeScript ~Any browser. Any host. Any OS. Open Source~
DEV-011_TypeScript ~Any browser. Any host. Any OS. Open Source~DEV-011_TypeScript ~Any browser. Any host. Any OS. Open Source~
DEV-011_TypeScript ~Any browser. Any host. Any OS. Open Source~
 
Visual C++で使えるC++11
Visual C++で使えるC++11Visual C++で使えるC++11
Visual C++で使えるC++11
 

More from cch-robo

Flutter_Forward_Extended_Kyoto-Keynote_Summary
Flutter_Forward_Extended_Kyoto-Keynote_SummaryFlutter_Forward_Extended_Kyoto-Keynote_Summary
Flutter_Forward_Extended_Kyoto-Keynote_Summarycch-robo
 
go_router が隠してくれるもの
go_router が隠してくれるものgo_router が隠してくれるもの
go_router が隠してくれるものcch-robo
 
Introduction_on_designing_test_in_flutter
Introduction_on_designing_test_in_flutterIntroduction_on_designing_test_in_flutter
Introduction_on_designing_test_in_fluttercch-robo
 
Google I/O 2021 Flutter 全体報告
Google I/O 2021 Flutter 全体報告Google I/O 2021 Flutter 全体報告
Google I/O 2021 Flutter 全体報告cch-robo
 
Dart / Flutter コードファイルジェネレート入門
Dart / Flutter コードファイルジェネレート入門Dart / Flutter コードファイルジェネレート入門
Dart / Flutter コードファイルジェネレート入門cch-robo
 
フラッター開発におけるシークレット情報取扱考察
フラッター開発におけるシークレット情報取扱考察フラッター開発におけるシークレット情報取扱考察
フラッター開発におけるシークレット情報取扱考察cch-robo
 
Dart言語の進化状況
Dart言語の進化状況Dart言語の進化状況
Dart言語の進化状況cch-robo
 
明示的アニメで、Flutterアニメーション入門
明示的アニメで、Flutterアニメーション入門明示的アニメで、Flutterアニメーション入門
明示的アニメで、Flutterアニメーション入門cch-robo
 
Dartでサーバレスサービス
DartでサーバレスサービスDartでサーバレスサービス
Dartでサーバレスサービスcch-robo
 
Pin-point rebuildable and non-rebuild custom widget
Pin-point rebuildable and non-rebuild custom widgetPin-point rebuildable and non-rebuild custom widget
Pin-point rebuildable and non-rebuild custom widgetcch-robo
 
Before lunch オプションを使って Flutterでstaging/release環境を切り替える
Before lunch オプションを使って Flutterでstaging/release環境を切り替えるBefore lunch オプションを使って Flutterでstaging/release環境を切り替える
Before lunch オプションを使って Flutterでstaging/release環境を切り替えるcch-robo
 
Android lint-srp-practice
Android lint-srp-practiceAndroid lint-srp-practice
Android lint-srp-practicecch-robo
 
Loose and fluffy_ddd_intro
Loose and fluffy_ddd_introLoose and fluffy_ddd_intro
Loose and fluffy_ddd_introcch-robo
 
Firebase Test Lab 無料枠を使ってみました。
Firebase Test Lab 無料枠を使ってみました。Firebase Test Lab 無料枠を使ってみました。
Firebase Test Lab 無料枠を使ってみました。cch-robo
 
ZTE OPEN を日本語化(バージョンアップ)してみる
ZTE OPEN を日本語化(バージョンアップ)してみるZTE OPEN を日本語化(バージョンアップ)してみる
ZTE OPEN を日本語化(バージョンアップ)してみるcch-robo
 
FirefoxOSで学ぶJavaScript作法
FirefoxOSで学ぶJavaScript作法FirefoxOSで学ぶJavaScript作法
FirefoxOSで学ぶJavaScript作法cch-robo
 

More from cch-robo (16)

Flutter_Forward_Extended_Kyoto-Keynote_Summary
Flutter_Forward_Extended_Kyoto-Keynote_SummaryFlutter_Forward_Extended_Kyoto-Keynote_Summary
Flutter_Forward_Extended_Kyoto-Keynote_Summary
 
go_router が隠してくれるもの
go_router が隠してくれるものgo_router が隠してくれるもの
go_router が隠してくれるもの
 
Introduction_on_designing_test_in_flutter
Introduction_on_designing_test_in_flutterIntroduction_on_designing_test_in_flutter
Introduction_on_designing_test_in_flutter
 
Google I/O 2021 Flutter 全体報告
Google I/O 2021 Flutter 全体報告Google I/O 2021 Flutter 全体報告
Google I/O 2021 Flutter 全体報告
 
Dart / Flutter コードファイルジェネレート入門
Dart / Flutter コードファイルジェネレート入門Dart / Flutter コードファイルジェネレート入門
Dart / Flutter コードファイルジェネレート入門
 
フラッター開発におけるシークレット情報取扱考察
フラッター開発におけるシークレット情報取扱考察フラッター開発におけるシークレット情報取扱考察
フラッター開発におけるシークレット情報取扱考察
 
Dart言語の進化状況
Dart言語の進化状況Dart言語の進化状況
Dart言語の進化状況
 
明示的アニメで、Flutterアニメーション入門
明示的アニメで、Flutterアニメーション入門明示的アニメで、Flutterアニメーション入門
明示的アニメで、Flutterアニメーション入門
 
Dartでサーバレスサービス
DartでサーバレスサービスDartでサーバレスサービス
Dartでサーバレスサービス
 
Pin-point rebuildable and non-rebuild custom widget
Pin-point rebuildable and non-rebuild custom widgetPin-point rebuildable and non-rebuild custom widget
Pin-point rebuildable and non-rebuild custom widget
 
Before lunch オプションを使って Flutterでstaging/release環境を切り替える
Before lunch オプションを使って Flutterでstaging/release環境を切り替えるBefore lunch オプションを使って Flutterでstaging/release環境を切り替える
Before lunch オプションを使って Flutterでstaging/release環境を切り替える
 
Android lint-srp-practice
Android lint-srp-practiceAndroid lint-srp-practice
Android lint-srp-practice
 
Loose and fluffy_ddd_intro
Loose and fluffy_ddd_introLoose and fluffy_ddd_intro
Loose and fluffy_ddd_intro
 
Firebase Test Lab 無料枠を使ってみました。
Firebase Test Lab 無料枠を使ってみました。Firebase Test Lab 無料枠を使ってみました。
Firebase Test Lab 無料枠を使ってみました。
 
ZTE OPEN を日本語化(バージョンアップ)してみる
ZTE OPEN を日本語化(バージョンアップ)してみるZTE OPEN を日本語化(バージョンアップ)してみる
ZTE OPEN を日本語化(バージョンアップ)してみる
 
FirefoxOSで学ぶJavaScript作法
FirefoxOSで学ぶJavaScript作法FirefoxOSで学ぶJavaScript作法
FirefoxOSで学ぶJavaScript作法
 

Recently uploaded

PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000Shota Ito
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxAtomu Hidaka
 
UPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdfUPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdffurutsuka
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Danieldanielhu54
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 
20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directoryosamut
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 

Recently uploaded (9)

PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
 
UPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdfUPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdf
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 
20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
 

Flutterを体験してみませんか

  • 3. はじめに このセッションは、Flutter 未体験者や初学者向けです。 ● Flutter は、どんなものなのかな? ● Flutter を、触ってみたいな。 そんなあなたに、Flutter の概要について紹介します。 GDG Kyoto は、 Google テクノロジーに興味のある 初心者から 専門家の方に、 開発者同士の交流や 新しいスキルへの学びを支援するコミュニティです。❤ Fluttr ⇒ iOS/Android/Web アプリが作れるフレームワーク 3
  • 4. Flutter とは 4 ● Fast Development ホットリロードでレイアウト変更も 素早く確認 ● Expressive and flexible UI 柔軟に組み合わることのできる ウィジェット&高速レンダリング。 ● Native Performance リリースアプリは、ネイティブマシンコード (ARM)にビルドされます。 Flutter 公式サイト https://flutter.dev/
  • 5. 5
  • 7. 表現力豊かで美麗なUI 7 ● Expressive, beautiful UIs Flutterには、ユーザーを魅惑する、表現力 豊かなウイジェットが組み込まれていま す。 マテリアルデザイン(美麗)、クパチーノ(iOS フレーバーを提供)、リッチモーションAPI、 スムーズで自然なスクロール、プラット フォームごとに雰囲気を変える ウィジェット があります。 Flutter 公式サイト https://flutter.dev/
  • 9. Dart言語による開発 9 Dart言語 公式サイト https://dart.dev/ ● Dart Language アプリは、Dart 言語で開発します。 Dart の言語は、 JavaScript の知見をベースに、 より良いアプリ開発や OOP のため、 Google が新たに設計した言語です。
  • 10. Dart 言語 公式資料 ● Tutorials https://dart.dev/tutorials ● Effective Dart https://dart.dev/guides/language/effective-dart ● A tour of the Dart language https://dart.dev/guides/language/language-tour ● API Reference https://api.dart.dev/stable/2.9.0/index.html 10
  • 12. Dart言語の歴史 WIKIPEDIA - Dart (programming language) より Dart 言語は、2010/10 にプロジェクトが立ち上がり、 2013/11 に Dart 1.0 安定版がリリースされました。 12 Dart 1.0: A stable SDK for structured web apps (2013/11/14) https://news.dartlang.org/2013/11/dart-10-stable-sdk-for-structured-web.html GOTO Conference 2011/10/10-12 Opening Keynote Presentation 紹介 "Dart, a new programming language for structured web programming" http://gotocon.com/aarhus-2011/presentation/Opening%20Keynote:%20Dart,%20a%20new%20programming%20l anguage%20for%20structured%20web%20programming
  • 13. Dart は、JavaScript の知見をベースとした Web開発のための新しい言語として誕生 13 http://gotocon.com/dl/goto-aarhus-2011/slides/GiladBracha_and_LarsBak_OpeningKeynoteDartANe wProgrammingLanguageForStructuredWebProgramming.pdf HISTORY BEHIND DART • After several years working on V8 for Chrome • Last year, Kasper Lund & I experimented with Spot  • a new simple language for the web  • based on the experiences from JavaScript • Spot was the prelude for the Dart project SO WHAT IS DART? • A simple and unsurprising OO programming language  • Class-based single inheritance with interfaces  • Optional static types  • Real lexical scoping  • Single-threaded  • Familiar syntax Keynote Presentation Slide より Dart 言語の大きな特徴として、オプションですが静的型付(実際は静的チェッカ ⇒参考元)をサポートし、プログラム構造を明示できるようインターフェースを使用した単 一継承クラスベースであることが掲げられています。
  • 14. JavaScript の困ったところは、バッサリ切り捨て 14 Dart FAQ Q. What does Google think of TypeScript? https://dart.dev/faq#q-what-does-google-think-of-typescript TypeScript maintains backwards compatability with JavaScript, whereas Dart purposely made a break from certain parts of JavaScript’s syntax and semantics in order to eradicate large classes of bugs and to improve performance. TypeScriptは、JavaScriptとの後方互換性を維持しますが、 Dartは意図的にJavaScriptの特定の構文とセマンティクス(意味解釈)を壊し、 バグの大元を取り去り、パフォーマンスを向上させています。
  • 15. JavaScript に構文が似ていても挙動は異なる 15 DartPad https://dartpad.dev/ JS : Firefox ウェブ開発 の ウェブコンソール結果 'use strict'; var num = 101; var str = '101'; console.log(num == str); // ⇒ true console.log(num === str); // ⇒ false Dart : DartPad での実行結果 void main() { var num = 101; var str = '101'; print(num == str); // ⇒ false } Dart は JavaScript と構文が似ていますが、暗黙の型変換を切り捨てています。 意図的にセマンティクスを変更しているので、同じようなコードであっても 別物と考える必要があります。
  • 16. Dart 2 から大規模変革開始 型システムが強化され 静的型付言語 となりました。 Webだけでなく、モバイルを含めたクライアント開発の (現在ではデスクトップ含むマルチプラットフォーム開発の) 言語に強化されています。 16 Announcing Dart 2: Optimized for Client-Side Development (2018/02/23) https://medium.com/dartlang/announcing-dart-2-80ba01f43b6 The Dart type system https://dart.dev/guides/language/type-system Announcing Dart 2 Stable and the Dart Web Platform (2018/08/08) https://medium.com/dartlang/dart-2-stable-and-the-dart-web-platform-3775d5f8eac7
  • 17. ● 2.0 sound type system ⇒ 静的型解決対応 (1.xコードからの移行必須化 ) ● 2.3 spread operator の追加 collection if と collection for の追加 ● 2.7 extension methods ⇒ 拡張メソッド をサポート ● 2.8 来たるべき null safety ⇒ null 安全 への布石 今後の進化は? 17 Dart language evolution https://dart.dev/guides/language/evolution Dart 2.0からの 進化の抜粋
  • 18. 18 Dart プロパティアクセス var button = querySelector('#confirm'); button.text = 'Confirm'; button.classes.add('important'); button.onClick.listen((e) => alert('Confirmed!')); Dart カスケード表記 querySelector('#confirm') // Get an object. ..text = 'Confirm' // Use its members. ..classes.add('important') ..onClick.listen((e) => alert('Confirmed!')); spread operator の前に、 cascade notation ⇒ カスケード表記を説明 Cascade notation https://dart.dev/guides/language/language-tour#cascade-notation- カスケード表記⇒ .. は、 同じオブジェクトのプロパティやメソッド指定する構文です。 これにより各メンバーへの連鎖的な設定が記述できます。 (.. の実態は演算子でなく、Dart 構文です)
  • 19. 19 Dart スプレッド演算子 var list = [1, 2, 3]; var list2 = [0, ...list]; assert(list2.length == 4); Dart スプレッド演算子(null認識表記) var list; var list2 = [0, ...?list]; assert(list2.length == 1); spread operator ⇒ スプレッド演算子は、 コレクションへの操作を 各要素への操作に展開します。 spread operator https://dart.dev/guides/language/language-tour#spread-operator スプレッド演算子⇒ … は、 ... 右辺のコレクションに対する操作を、 その各要素への操作として展開します。 これによりリスト全要素の別リストへの挿入も手軽に記述できます。
  • 20. 20 Dart コレクション if var nav = [ 'Home', 'Furniture', 'Plants', if (promoActive) 'Outlet' // true 時のみ挿入 ]; Dart コレクション for var listOfInts = [1, 2, 3]; var listOfStrings = [ '#0', for (var i in listOfInts) '#$i' ]; // listOfStrings ⇒ ['#0','#1','#2','#3'] collection if / collection for は、 コレクションへの 条件 / 繰返 指定付きの要素挿入です。 collection if / collection for https://dart.dev/guides/language/language-tour#collection-operators コレクション if と コレクション for により、、 コレクションへの要素挿入処理の記述が手軽になります。
  • 21. 21 Dart 拡張メソッド extension CountService on String { int countExclamations() => this.length - this.replaceAll("!","").length; } void main() { print("Hello, world!!!".countExclamations()); // 3 が表示される。 } 【参考】Kotlin 拡張関数 fun String.countExclamations(): Int = this.length - this.replace("!","").length fun main() { println("Hello, world!!!".countExclamations()) // 3 が表示される。 } extension methods ⇒ 拡張メソッドは、 既存クラスにメソッドやプロパティを追加し(たように見せ)ます。 Extension methods https://dart.dev/guides/language/extension-methods
  • 22. null 安全に移行すると、 既存の変数宣言は、null 不可型 の変数宣言になります。 null も許すなら、null 許容型 の変数宣言への変更必須です。 null 不可型変数には、nullが設定されなことが保証されますが、 null 安全は、まだテクニカルプレビューなので製品版には使わないで! ここでは表記単純化のため non-null や non-nullable を null 不可、 nullable を null許容 …と共通意訳していることに留意ください。 22 Understanding null safety https://dart.dev/null-safety/understanding-null-safety Sound null safety https://dart.dev/null-safety null safety ⇒ null 安全
  • 23. 23 Dart の Null 安全 : DartPad with null safety での実行結果 void main() { String? nullableStr = null; // OK! (null 許容型の String として宣言) int nonNullNum = 100; // OK! (null 不可型の int として宣言) int? nullableNum = null; // OK! (null 許容型の int として宣言) nonNullNum = nullableNum; // Type mismatch: inferred type is Int? but Int was expected String nonNullStr = null; // Null can not be a value of a non-null type String } DartPad with null safety https://nullsafety.dartpad.dev/ null safety ⇒ null 安全では、 型宣言? で null 許容型、なければ常に null 不可型になる。
  • 24. 24 class Sample { // 初回アクセスされるまでに初期化されていれば良い、 null 不可型宣言フィールド late String lateStr; void init() { print("late -> "); lateStr = "Hello"; } } void main() { Sample sample = Sample(); sample.init(); print("lateStr=${sample.lateStr}"); // late -> lateStr=Hello } null safety ⇒ null 不可なフィールドは、 late 型宣言で 遅延設定フィールド に修正する。 late を付けて宣言しないとエラーになる。 Error: Field 'lateStr' should be initialized because its type 'String' doesn't allow null. String lateStr; ^^^^^^^
  • 25. 25 null safety ⇒ null 安全では、 null 不可なオプション引数に、初期値が必須になる。 void present( String name, {String color}) { print('I send you a $color $name.'); } Error: Optional parameter 'color' should have a default value because its type 'String' doesn't allow null. String name, {String color}) { ^^^^^ void main() { present('rose', color:'red'); } void present( String name, {String color='white'}) { print('I send you a $color $name.'); // I send you a red rose. が表示される。 } オプション引数に、初期値があるとき。 オプション引数に、初期値がないとき。
  • 26. 26 Flutter Day Livestream | Session 3: Dart https://www.youtube.com/watch?v=ZxSyZHq8gUg&feature=youtu.be&t=1618 null safety ⇒ null 安全に移行するには、 既存ソースからの移行作業が必須になります。 nnbd_migration 0.1.0 https://pub.dev/packages/nnbd_migration null 安全は、魅力的ですが、 既存のコードやライブラリは、 移行作業(コード修正)が必須です このため Dart チームは、 移行ツールを提供しています。 Note: the null safety migration tooling is in an early state and may have bugs and other issues. For best results, use SDK version 2.9.0-10.0.dev or higher.
  • 27. 27 Kotlin Playground https://play.kotlinlang.org/ 【参考】Kotlin の Null 安全 : Kotln Playground での実行結果 fun main() { var nullableNum : Int? = null // OK! (Null 許容型の Int として宣言) var nonNullNum : Int = 100 // OK! (Null 不可型の Int として宣言) var nullableStr : String? = null // OK! (Null 許容型の String として宣言) nonNullNum = nullableNum // Type mismatch: inferred type is Int? but Int was expected var nonNullStr : String = null // Null can not be a value of a non-null type String } 【参考】 Kotlin の Null Safety ⇒ Null 安全も、 型宣言? であれば Null 許容型、なければ常に Null 不可型
  • 28. 28 class Sample { // 初回アクセスされるまでに初期化されていれば良い、 Null 不可型宣言フィールド lateinit var lateStr : String // 初回アクセス時に初期化の移譲関数が実行される、 Null 不可型宣言フィールド val lazyNum : Int by lazy { print("lazy -> "); 100 } fun init() { print("late -> "); lateStr = "Hello" } } fun main(args: Array<String>) { val sample = Sample(); sample.init() println("lateStr=${sample.lateStr}") // late -> lateStr=Hello println("lazyNum=${sample.lazyNum}") // lazy -> lazyNum=100 } 【参考】 Kotlin の Null 安全な、遅延設定フィールドは、 lateinit か lazy 移譲関数を指定する。
  • 29. 29 Flutter Day Livestream | Session 3: Dart https://www.youtube.com/watch?v=ZxSyZHq8gUg&feature=youtu.be&t=2650 #AskFlutter #FlutterDay 回答より rich enum types や sealed classes 導入について、何度か検討したが、 現時点では約束できないそうです。 今後の進化は?
  • 30. 30 Are there any sealed classes alternatives in Dart 2.0? https://stackoverflow.com/questions/54317000/are-there-any-sealed-classes-alternatives-in-dart-2-0 【補足】 Sealed Class は、 完全ではありませんが擬似コードは作れます。 【参考】Kotlin シールドクラス例 sealed class MyState { data class Success(val data: List<MyObject>) : MyState() data class Error(val error: String) : MyState() } シールドクラスは、継承可能な範囲(派生先)を制限するクラス これにより派生物ごとの処理制御が保証可能になります。 stack overflow に Dartでの擬似コードの回答例がありました。
  • 31. 31 Algebraic Data Types (ADTs, Sealed Classes, Enum with associated values) https://github.com/dart-lang/language/issues/349 Dart での擬似コード回答例 class MyState { MyState._(); factory MyState.success(String foo) = MySuccessState; factory MyState.error(String foo) = MyErrorState; } class MyErrorState extends MyState { MyErrorState(this.msg): super._(); final String msg; } class MySuccessState extends MyState { MySuccessState(this.value): super._(); final String value; } 擬似コードでも、 想定を満たしますが、 Kotlin の シールドクラスは、 定義されたファイル以外 に、指定されたクラスの 他の実装がないことまで 保証できます。 dart-lang に ISSUE は立ってます。
  • 32. Flutterアプリのプログラム 32 ● 画面もロジックもDartで作成 Flutter アプリは、画面レイアウトや UI のみ ならず JSONフェッチなどの機能も 全てコードで作成します。 ● Flutter for Web Flutter は、モバイル開発だけでなく、 ベータ版ですが Web アプリも作れます。 画面レイアウトも UI も機能やロジックも、 Flutter は全て Dart コード で作成するという プログラムコードは、どんなものでしょう。
  • 33. Flutterアプリのプログラム開発例 東京都 新型コロナウイルス感染症 対策サイト の 最新検査状況を表示する Web アプリを作ってみました。 33 ホスティングしていないので、 ローカルサーバで動作させて います。 この画面作成とHTMLスクレイピングの 全コードを紹介します。
  • 34. Flutter for Web でのプログラミング アプリを作るためのプログラミングは、 どのようなものなのか紹介します。 まずは、画面作成から。 34
  • 35. 画面作成の全ソース(1/4) 35 import 'package:flutter/material.dart'; import 'tokyo_stop_covid19.dart'; PositiveSituation jsonModel; Future<void> main() async { jsonModel = await TokyoStopCovid19.createPositiveSituation(); runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyPage(), ); } } class MyPage extends StatelessWidget { const MyPage({Key key}) : super(key: key); Widget _customText(String label, {double fontSize = 12.0, FontWeight fontWeight = FontWeight.normal}) { return Expanded( child: Container( alignment: Alignment.center, margin: const EdgeInsets.all(4.0), child: Text('$label', style: TextStyle(fontSize: fontSize, fontWeight: fontWeight)) ), ); } 画面を作る my_app.dart の全ソースは、 4ページ分しかありません。 この後、スライドのダウンロード先を紹介します。
  • 36. 画面作成の全ソース(2/4) 36 @override Widget build(BuildContext context) { print('jsonModel=$jsonModel'); return Scaffold( backgroundColor: Colors.white70, body: Center( child: Container( decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.black54, spreadRadius: 1.0, blurRadius: 10.0, offset: Offset(10, 10), ), ], ), child:Card( color: Colors.white, child: Container( 上の画面は、 この4ページ分のコードで仕上がります。
  • 37. 画面作成の全ソース(3/4) 37 child:Card( color: Colors.white, child: Container( width: 500.0, margin: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 0.0), child:Column( mainAxisSize: MainAxisSize.min, children:[ Container( alignment: Alignment.center, margin: const EdgeInsets.all(4.0), child: Text('東京都 検査陽性者の状況', style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.w600)), ), Row( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.max, children: <Widget>[ _customText('累計'), _customText('入院中'), _customText('軽症〜中等症'), _customText('重症'), _customText('死亡'), _customText('退院'), ], ), Divider(height: 14.0, color: Colors.black12), Flutter には、 Material Design に準拠した Widget と呼ばれる UI やレイアウトのコン ポーネント・パーツが たくさん用意されています。
  • 38. 画面作成の全ソース(4/4) 38 Divider(height: 14.0, color: Colors.black12), Row( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.max, children: <Widget>[ _customText(jsonModel?.cumulative.toString() ?? '0'), _customText(jsonModel?.hospitalized.toString() ?? '0'), _customText(jsonModel?.mild2moderate.toString() ?? '0'), _customText(jsonModel?.severe.toString() ?? '0'), _customText(jsonModel?.death.toString() ?? '0'), _customText(jsonModel?.discharge.toString() ?? '0'), ], ), Container( alignment: Alignment.centerRight, margin: const EdgeInsets.all(4.0), child: Text('${jsonModel?.updateString() ?? DateTime.now()} 更新', style: TextStyle(fontSize: 14.0)), ), ], ), ), ), ), ), ); } } _customText() (1ページめの定義参照) のように、 特定UIをこなしてくれる、独自のコンポーネントを プログラムで定義することもできます。
  • 39. Flutter for Web でのプログラミング サンプルの Webアプリでは、最新の検査状況を 東京都 新型コロナウイルス感染症 対策サイトページから スクレイピングして JSON データに変換しています。 続いて、HTML スクレイピング。 39
  • 40. スクレイピングの全ソース(1/4) 40 import 'dart:convert'; // ignore:directives_ordering import 'package:http/http.dart' as http; /// 東京都 都内の最新感染動向 を表すクラス class TokyoStopCovid19 { /// HTML スクレイピングによる 検査陽性者状況 JSON 取得 static Future<Map<String, dynamic>> scrapingPositiveSituation() async { http.Response response; // 東京都 都内の最新幹線動向 サイト const String host = ‘stopcovid19.metoro.tokyo.lg.jp'; const String path = '/'; const String url = 'https://' + host + path; print('beore scrapingPositiveSituation() => request.url=$url'); response = await http.get(url); print('after scrapingPositiveSituation() => request.url=$url'); if (response.statusCode != 200) { throw new StateError('HTTP Response status code is ${response.statusCode}'); } // 都内の最新幹線動向 ページの HTML body テキスト final String htmlBody = utf8.decode(response.bodyBytes); // 検査要請者の状況ブロックのみ HTMLテキスト抽出 東京都のページから、 最新の検査状況をスクレイピングする tokyo_stop_covid19.dart の 全ソースは4ページ分だけです。 https://stopcovid19.metro.tokyo.lg.jp/ から、 HTML テキストを直接取得して、 スクレイピングしています。
  • 41. スクレイピングの全ソース(2/4) 41 // 都内の最新幹線動向 ページの HTML body テキスト final String htmlBody = utf8.decode(response.bodyBytes); // 検査要請者の状況ブロックのみ HTMLテキスト抽出 bool isExtracting = false; final String extracts = htmlBody.split(RegExp('n')).where( (String line) { if (line.contains(RegExp('検査陽性者の状況'))) isExtracting = true; if (line.contains(RegExp('検査実施状況'))) isExtracting = false; return isExtracting; } ).toList().join(); // 種別〜人数ブロックのみ HTMLテキスト抽出 isExtracting = false; List<String> contents = extracts.split(RegExp('> ?<')).where( (String line) { if (line.contains(RegExp('class="content_1gFZ-"'))) isExtracting = true; if (line.contains(RegExp('class="unit_25C4Z"'))) isExtracting = false; return isExtracting; } ).join().split(RegExp('div class="content_1gFZ-"')); // 更新日付ブロックのみ HTMLテキスト抽出 isExtracting = false; String datetime = extracts.split(RegExp('> ?<')).where((String line) { return line.contains(RegExp('time datetime=')); }).join(); 文字が小さくて読めないと思いますので、 この後、スライドのダウンロード先を紹介します。 Dart 言語は、 JavaScript(ES2015)に似ています。 class や async / await、アロー関数、 コレクションのストリーム処理などが 使えます。
  • 42. スクレイピングの全ソース(3/4) 42 // 種別〜人数+更新日付ブロックのみ HTMLテキスト contents.add(datetime); // 抽出 HTML テキストから JSON を生成する。 final Map<String, dynamic> json = contents.map<Map<String,dynamic>>( (String content) { Map<String, dynamic> el; if (content.contains(RegExp('累計'))) el = {'cumulative': _extractNum(content)}; if (content.contains(RegExp('入院'))) el = {'hospitalized': _extractNum(content)}; if (content.contains(RegExp('軽症'))) el = {'mild2moderate': _extractNum(content)}; if (content.contains(RegExp('重症'))) el = {'severe': _extractNum(content)}; if (content.contains(RegExp('死亡'))) el = {'death': _extractNum(content)}; if (content.contains(RegExp('退院'))) el = {'discharge': _extractNum(content)}; if (content.contains(RegExp('更新'))) el = {'updatetime': _extractDatetime(content)}; return el; } ).reduce( (Map<String, dynamic> prev, Map<String, dynamic> curr) { curr.addAll(prev ?? {}); return curr; } ); print('json=$json'); return json; } /// 数値抽出関数 スクレイピングした HTML テキストから、 JSON データ ⇒ Map<String, dynamic> に 変換しています。
  • 43. スクレイピングの全ソース(4/4) 43 /// 数値抽出関数 static int _extractNum(String content) { final String num = content .replaceFirst(RegExp('^[^0-9]*'), '') .replaceFirst(RegExp('[^0-9]*$'), ''); return int.parse(num); } /// 日付抽出関数 static DateTime _extractDatetime(String content) { final String date = content .replaceFirst(RegExp('^time datetime="'), '') .replaceFirst(RegExp('".*$'), ''); return DateTime.parse(date); } } こちらは、内部で利用する、 ユーティリティ関数となります。 全体的に JavaScript に似かよったプログラムになっています。
  • 44. スクレイピングの補足 44 検査陽性者の状況</h3> </div> <div class="DataView-Description"></div> <div><p class="note_3ycFr">(注)チャーター機帰国者、クルーズ船乗客等は含まれていない </p></div> <div class="DataView-CardText"> <ul aria-label="検査陽性者の状況" class="container_37WEO"><li class="box_2dey9 parent_23pyN confirmed_P-yFc"> <div class="pillar_F62Yl"><div class="content_1gFZ-"><span>陽性者数<br>(累計)</span> <span><strong>154</strong> <span class="unit_25C4Z">人</span></span></div></div> <ul class="group_1ksdS"><li class="box_2dey9 parent_23pyN hospitalized_3w7PT"> <div class="pillar_F62Yl"><div class="content_1gFZ-"><span>入院中</span> <span><strong>119</strong> <span class="unit_25C4Z">人</span></span></div></div> <ul class="group_1ksdS"><li class="box_2dey9 minor_1RUXC"><div class="pillar_F62Yl"> 〜 省略 〜 <li class="box_2dey9 recovered_JzYjB"><div class="pillar_F62Yl"><div class="content_1gFZ-"><span>退院</span> <span><strong>31</strong> <span class="unit_25C4Z">人</span></span> </div></div></li></ul></li></ul></div> <div class="DataView-Description"></div> 〜 省略 〜 <div class="DataView-Footer"><div class="Footer-Left"><div><!----></div> <div> <a href="/cards/details-of-confirmed-cases" class="Permalink"> <time datetime="2020-03-23T21:15:00">2020/03/23 21:15 更新</time></a></div></div> <div class="Footer-Right"><button class="DataView-Share-Opener"> <svg width="14" height="16" viewBox="0 0 14 16" fill="none" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="検査陽性者の状況のグラフをシェア"> 〜 省略 〜 <div class="DataCard col-md-6 col-12" data-v-59bfe8e7> <div class="DataView v-card v-sheet theme--light"><div class="DataView-Inner"> <div class="DataView-Header"><h3 class="DataView-Title"> 検査陽性者の状況 部から抽出した HTML テキスト <div class="content_1gFZ-"> <span>入院中</span> <span> <strong>119</strong> <span class="unit_25C4Z">人</span> </span> </div> 3月23日のコンテンツでは、 種別ごとの DIV タグには、 class="content_1gFZ-" が割り当てられ、 人数を表す SPAN タグには、 class="unit_25C4Z" が割り当てられている …ことを利用して抽出しています。
  • 45. Flutter での Webアプリ開発 画面のレイアウトや UI を全てコードで記述することや Dart言語は、JavaScript とあまり変わらないことを 確認いただけましたでしょうか。   Flutter 公式資料 Flutter for web developers ⇒ CSS や HTML と Flutter コードの違い説明 https://flutter.dev/docs/get-started/flutter-for/web-devs Building a web application with Flutter ⇒ Flutter での Webアプリ作成手順 https://flutter.dev/docs/get-started/web 45
  • 46. お詫び dart言語は、最終的に JavaScript に変換されるため、 外部サイト(東京都サイト)からの HTML テキスト取得は、 サイトをまたがる CORS ポリシー違反になります。 このためサンプル Web アプリは、 ブラウザの CORSポリシーを無効 にしなければ、 実行できません。 46
  • 47. CORSポリシーを一時的に無効にする ● CORSポリシーを無効にした Chrome を起動する。 Webアプリから外部サイトのリソース (JSON情報など)を取得する必用がある場合は、 起動オプションで CORS ポリシーを無効にした Chorome を開き、それで実行させます。 【参考】Run Chrome browser without CORS ⇒ https://alfilatov.com/posts/run-chrome-without-cors/ この方法は、あくまでデバッグなどでの一時的な対処です。 本来は、アクセスするサーバ側で Access-Control-Allow-Origin などの設定をするのが正式です。 CORSポリシーが無効化されるのは、上記で起動した Chrome ウィンドウだけなことに注意! 47 # MacOS で、セキュリティポリシーを無効にした Chrome を起動させます。(下記は一行コマンド) $ open -n -a /Applications/Google Chrome.app/Contents/MacOS/Google Chrome --args --user-data-dir="/tmp/chrome_dev_test" --disable-web-security # Windows 10で、セキュリティポリシーを無効にした Chrome を起動。(下記は一行コマンド) > "C:Program Files (x86)GoogleChromeApplicationchrome.exe" --disable-web-security --disable-gpu --user-data-dir=~/chromeTemp # Linux で、セキュリティポリシーを無効にした Chrome を起動。(下記は一行コマンド) $ google-chrome --user-data-dir="/tmp/chrome_dev_test" --disable-web-security
  • 49. むすび Flutter って なんだか良さそう …と思っていただけましたでしょうか。 GDG Kyoto は、 Google テクノロジーに興味のある 初心者から 専門家の方に、 開発者同士の交流や 新しいスキルへの学びを支援するコミュニティです。 Flutter 開発についても取り組んでいますので、お気軽に参加ください ❤ 49