Dart List

List 使い方

Dart List チートシート

every

Listの全てのエレメントが条件を満たすかチェック。返り値はbool

1
final allEven = items.every((item) => item % 2 == 0);
1
const allEven = items.every(item => item % 2 == 0);

map

すべての要素に対して与えられた関数を呼び出し、その結果からなる新しい配列を生成

1
final newItems = items.map((item) => item + 1).toList();
1
const newItems = items.map(item => item + 1);

fold

すべての要素に対して与えれた関数を呼び出し、単一の値にして返す

初期値を指定する順番が、JavascriptとDartでは異なる

1
2
3
4
final totalPrices = items.fold(0, (total, current) {
total = total + current.price;
return total;
});
1
2
3
4
const totalPrices = items.reduce((total, current) => {
total = total + current.price;
return total;
}, 0);

add

配列の末尾に要素を追加。Javascriptは新しい配列の長さを返すが、Dartはvoidを返す

1
items.add(42);
1
items.push(42);

contains

特定の要素が配列に含まれているかどうかチェック。返り値はbool

1
final includes = items.contains(42);
1
const includes = items.includes(42);

Dart DatTime

DateTimeオブジェクトを文字列へ変換

1
2
3
4
import 'package:intl/intl.dart';
DateFormat dateFormat = DateFormat('yyyy-MM-dd HH:mm:ss');

String str = dateFormat.format(DateTime.now());

文字列をDateTimeオブジェクトへ変換

1
2
3
4
import 'package:intl/intl.dart';
DateFormat dateFormat = DateFormat('yyyy-MM-dd HH:mm:ss');

DateTime dateTime = dateFormat.parse('2020-02-02 20:20:20');

アンダースコア「_」のみの変数

構文上、変数が必要だが、使わないとアナライザ(構文チェッカ)が
「その変数は使われていない」というエラーを出す

アンダースコア「_」の変数を使うと、このエラーを抑制できる

1
2
3
for (var _ in new Iterable.generate(1)) {
print('no warnings');
}

Flutter FutureBuilder と StreamBuilder

Future

  • 非同期処理
  • 値を取得すると処理が終了

Stream

  • 非同期処理
  • ストリームが開いている間、ずっと値が流れてくる
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var controller = StreamController<int>();
var stream = controller.stream;

// ストリームを listen() しておくと、そのデータを受け取れる
var subscription = stream.listen((data) => print('listen=$data'),
onError: (error) {
//エラー処理
},
cancelOnError: false,
onDone: () {
//完了時に呼ばれる
});

// ストリームにデータを流す
controller.sink.add(1);

// 1秒待機
await Future.delayed(Duration(second: 1));

// ストリームを閉じる
subscription.cancel();
controller.close();

FutureBuilder

  • FutureクラスをUIで扱うためのウィジェット
    • future に、終了を待ちたい非同期処理を指定
    • builder に、その結果を受けてWidget生成する処理を指定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
FutureBuilder(
future: Repository().fetch(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snaphost.hasError) {
return // エラー表示のウィジェットを記述
}
if (!snapshot.hasData) {
return // データ無し表示のウィジェットを記述
}
// データ表示
return Text('${snapshot.data}');
} else {
// 処理中の表示
return const CircularProgressIndicator();
}
},
),
1
2
3
4
5
6
7
class Repository {
Future<int> fetch() {
return Future.delayed(Duration(second: 1).then((_) {
return 1;
});
}
}
1
2
3
4
5
6
7
8
9
10
child: Column(
children: [
FutureBuilder<PackageInfo>(
future: PackageInfo.fromPlatform(),
builder: (context, snapshot) {
return Text('Ver. ${snapshot.data?.version ?? '-'}');
},
),
]
)

StreamBuilder

  • StreamクラスをUIで扱うためのウィジェット
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
StreamBuilder<int> (
stream: logic.value,
builder: (context, snapshot) {
if (snaphost.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
return ErrorWidget(snapshot.error);
}
if (!snapshot.hasData) {
retrun Container();
}
return Text('${snapshot.data}');
} else {
return const CirculearProgressIndicator();
}
},
),

Dart 関数

関数の基本形

1
2
3
戻り値の型 function_name (引数の型 引数名) {
return 戻り値;
}

名前付きパラメータ

  • {} で引数を囲むと、呼び出す際に名前の指定が必要に
  • {} で引数を囲むと、任意の引数になる
  • 必須にしたければ @required アノテーションをつける
  • 引数の一部だけに使う場合は、末尾にもってくる
1
2
3
4
5
6
7
8
# 定義
void example({bool bold, bool hidden}) {....};

# 呼び出し
example(bold: true, hidden: false);

# 引数を必須にする
void example({@required bool bold, bool hidden}) {....};

オプショナルパラメータ

  • [] で引数を囲むと、任意の引数になる
  • 引数の一部だけに使う場合は、末尾にもってくる
1
2
3
4
5
# 定義
String say(String from, [String msg]) {...};

# 呼び出し
say('Bob');

デフォルト値

  • 名前付きパラメータ、オプショナルパラメータ ともにデフォルト値を設定可能
1
String say({String from = 'Bob'}, [String msg = 'hello']) {...};

匿名関数

1
2
3
(引数の型 引数名) {
return 戻り値;
}
1
2
3
4
var hello = (name) {
return 'Hello, ${name}';
}
print(hello('foo'));

Dart言語 演算子

条件式

  • conditionがtrueならexpr1を計算して返す、そうでなければ、expr2を計算して返す
1
condition ? expr1 : expr2
  • expr1が非nullの時はその値を返す、そうでなければ、expr2を計算して返す
1
expr1 ?? expr2

Conditional member access operator「?.」

https://dart.dev/guides/language/language-tour#overridable-operators

  • オブジェクト(レシーバー)がnullの場合にメソッドを呼ぶとエラーになるので、エラーにせずに戻り値としてnullを返す事が出来る演算子
1
2
String target = null;
var length = target?.trim()?.toLowerCase()?.length ?? 0; // 結果は「0」

カスケード記法 「..」

https://dart.dev/guides/language/language-tour#cascade-notation-

  • レシーバーのオブジェクトを返す演算子
  • 一時変数を作成する手間が省け、簡潔な記述が出来る
1
2
3
4
5
6
7
8
final addresBook = (AddressBookBuilder()
...name = '山田'
...email = 'test@example.com'
...phone = (PhoneNumberBuilder()
...number = '999-9999-9999'
...label = 'home')
.build())
.build();

Spreads記法 「…」「…?」

https://dart.dev/guides/language/language-tour#spread-operator

  • リストの全ての要素を別のリストに挿入できる演算子
1
2
3
var list = [1, 2, 3];
var list2 = [0, ...list];
assert(list2.length == 4);
  • nullの可能性がある場合は「…?」を使う
1
2
3
var list;
var list2 = [0, ...?list];
assert(list2.length == 1);
  • 利用例
1
2
3
4
5
6
7
8
9
10
11
12
Widget build(BuildContext context) {
return CupertionPageScaffold(
child: Column(
children: [
buildHeader(),
...buildContents(),
...buildContents2(),
buildFooter(),
],
),
);
}

Collection if

  • リストに作成時に値を含めるかどうかの条件分岐を記述できる
1
2
3
4
5
6
var nav = [
'Home',
'Furniture',
'Plants',
if (promoActive) 'Outlet'
];
  • 利用例
1
2
3
4
5
6
7
8
9
10
11
12
Widget build(BuildContext context) {
return CupertionPageScaffold(
child: Column(
children: [
buildHeader(),
...buildContents(),
if (wantContents2) ...buildContents2(),
buildFooter(),
],
),
);
}

Collection for

  • リスト作成時に、別のリストを操作しながらリストに追加する処理を記述できる
1
2
3
4
5
6
7
var listOfInts = [1, 2, 3];
var listOfStrings = [
'#0'
for (var i in listOfStrings) '#$i'
];
assert(listOfStrings[1] == '#1');
assert(listOfStrings.length == 4);

Dart Futureクラス

Future

  • 非同期処理を簡潔に扱うための仕組み
  • 他の言語では、プロミス と呼ばれる
1
2
3
4
5
6
7
8
9
repository.fetchUser(100).then((User user) {
return repository.fetchCompany(user.companyId);
}).then((Company company) {
// 成功時の処理
}).catchError(error) {
// エラー時の処理
}).whenComplete() {
// どちらかが終わったら呼ばれる
});

async/await

  • Futureクラスの記述の可読性をあげるシンタックスシュガー
  • 戻り値は、Future型でないと利用できないので注意
  • 上のコードを以下のように書く事が出来る
1
2
3
4
5
6
7
8
9
10
11
Future<String> findCompanyName(int userId) async {
try {
var user = await repository.fetchuser(userId);
var company = await repository.fetchCompany(user.companyId);
return company.name;
} catch(error) {
// エラー時の処理
} finally {
// 終了時の処理
}
}

Dart言語 コンストラクタ

クラスと同じ名前の関数がコンストラクタ

生成的コンストラクタ(一般的なコンストラクタ)

1
2
3
4
5
6
7
8
9
class Color {
int red;
int green;
int blue;
Color({int red, int green, int blue}) {
this.red = red;
this.green = green;
this.blue = blue;
}

自動フィールド初期化

  • Dartで使われる一般的な書き方
  • 上のコードと同じ意味
1
2
3
4
5
6
7
class Color {
int red;
int green;
int blue;
// 同名のフィールドに自動代入する
Color(this.red, this.green, this.blue);
}

名前付きコンストラクタ

  • クラスに複数のコンストラクタを実装できる
  • それぞれのコンストラクタの意味を明確に出来る
1
2
3
4
5
6
7
8
9
10
11
12
class Color {
int red;
int blue;
int green;

// 別の引数を受け取るコンストラクタを作成
Color.fromString(String colorText) {
this.red = int.parse(colorText.substring(0, 2), radix: 16);
this.blue = int.parse(colorText.substring(2, 4), radix: 16);
this.green = int.parse(colorText.substring(4, 6), radix: 16);
}
}

コンストラクタのリダイレクト

1
2
3
4
5
6
7
8
9
10
11
12
class Child extends Base {
// 親クラスの「名前付きコンストラクタ」を呼び出す
Child(String value): super.fromString(value);

// 親クラスの「通常のコンストラクタ」を呼び出す
Child.ex(): super('test') {
//...
};

// 自クラスの別の「名前付きコンストラクタ」を呼び出す
Child.delegate(): this.fromString('');
}

初期化リスト

  • コンストラクタ本体を実行する前に、インスタンス変数を初期化できる
1
2
3
4
5
6
7
8
class Line {
final int length;
final Color color;

// 何か処理を実行してからフィールドに代入する
Line({@required this.length, @required String colorText}):
this.color = Color.fromString(colorText);
}

初期化される処理の順序

  1. 初期化リスト (initializer list)
  2. スーパークラスのコンストラクタ
  3. 子クラスのコンストラクタ

初期化リスト + assert機能

1
2
3
4
5
6
7
8
9
class Article {
final String title;
final String body;

// 引数の条件確認を行う
Article({@required this.title, @required this.body}):
assert(title != null),
assert(body != null);
}
1
2
3
4
5
6
7
class Item extends Base {
final String name;

Item({@required this.name}):
asesrt(name != null),
supser(); // 親クラスのコンストラクタを呼び出す場合は最後に書く
}

ファクトリコンストラクタ

  • ファクトリコンストラクタはインスタンスが作成されない
  • シングルトンのデザインパターンで利用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
clas GlobalContext() {
static GlobalContext _instance;

// 「_」から始まるのでprivateなコンストラクタ
GlobalContext._() {
//...
}

// ファクトリコンストラクタで「生成的コンストラクタ」を使う
factory GlobalContext() {
if (_instance == null) {
_instance = GlobalContext._();
}
return _instance;
}

// ファクトリコンストラクタで「名前付きコンストラクタ」を使う
factory GlobalContext.getWithRefresh() {
_instance = null;
return GlobalContext();
}
}

定数コンストラクタ

  • コンパイル時に定数オブジェクトをインスタンス化したい場合に利用
  • コンストラクタには「const」キーワードを付け、「const」キーワードでインスタンスを生成
1
2
3
4
5
6
7
8
9
10
11
12
class Pet{
final name;
const Pet(this.name);
}

final dog = const Pet('Pochi');

void main(){
final Pet cat = new Pet('Mike');
print(dog.name); // => Pochi
print(cat.name); // => Mike
}
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×