Android Studio Line行数の設定

Android Studioで、1行の行数をセットをする。

Editor > Code Style > Dart > Line Length

Flutter AndroidX へのマイグレーション

プロジェクトフォルダを右クリックし、
「Flutter」 > 「Open Android module in Android Studio」でAndroidプロジェクトを開く

メニュー「Refactor」 > 「Migrate to AndroidX」を選択

「Migrate」をクリック

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');

Android Studio StatefulWidget/StatelessWidget 雛形作成

Android Studioのライブテンプレート機能で簡単に雛形を作成できる

StatefulWidget の雛形を作成

1
stful

StatelessWidget の雛形を作成

1
stless

Flutter Firebase 書き方

参照

Eメール認証

ユーザー登録

1
2
3
4
5
6
7
8
9
10
11
12
13
14
FirebaseUser user; 
void _registerUser(String _email,String _password) async {
user = (await _auth.createUserWithEmailAndPassword(
email: _email,
password: _password,
)).user;
if (user != null) {
// User registered successfully
// Add user details in realtime database or cloudfirestore
} else {
// User not registered Successfully
}
}
}

ログイン

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
final FirebaseUser user  
void _signInWithEmailAndPassword(String _email,String _password) async {
user = (await _auth.signInWithEmailAndPassword(
email: _email,
password: _password,
)).user;
if (user != null) {
// Login successful
// Navigate to main page
} else {
// Invalid email and password
// Navigate to registration page
}
}
}

Firebase

データ保存

  • add は、新しいDocumentIdを生成して、新しいレコードとして保存
1
2
3
4
5
Future<void> newGroup() {
return Firestore.instance.collection("hoge").add({
"hoge": hogehoge
});
}
  • set は、ドキュメントの追加、上書き
  • 既にドキュメントが存在すると、ドキュメントごと全て上書き
  • mergeオプションをつければ、fieldだけの一部追加も可能
1
2
3
4
5
6
Future<void> editGroup() {
var db = Firestore.instance;
return db.collection("group").document(groupID).setData({
"hoge": hogehoge
});
}

データ更新

  • update は、ドキュメントのfieldの値を更新
  • ドキュメントがないとエラーになる
1
2
3
4
5
6
Future<void> _uploadImage(String documentId,) async {
return Firestore.instance
.collection("group")
.document(documentId)
.updateData({"documentId": documentId});
}

データ参照

  • データ取得
1
2
3
4
5
6
Stream<QuerySnapshot> getGroupItem(String groupId) {
return Firestore.instance
.collection("group")
.document(groupId)
.get();
}
1
2
3
4
5
6
7
8
Future<Group> getGroupInfo(String groupId) async {
var document = Firestore.instance.collection("group").document(groupId).get();
return await document.then((doc) {
return Group.setGroup(doc);
});
}
// 呼び出し
var groupInfo = await helper.getGroupInfo(widget.groupId);
  • Streamのsnapshotを取得
1
2
3
4
5
6
Stream<QuerySnapshot> getGroupItem(String groupId) {
return Firestore.instance
.collection("group")
.document(groupId)
.snapshots();
}
  • Streamのsnapshotを更新日付け順で取得
1
2
3
4
5
6
Stream<QuerySnapshot> getGroupItem(String groupId) {
return Firestore.instance
.collection("group")
.orderBy("updated_at", descending: true)
.snapshots();
}
  • Streamのsnapshotをタイトルが同じものだけ取得
1
2
3
4
5
6
Stream<QuerySnapshot> searchGroup(String title) {
return Firestore.instance
.collection("group")
.where("title", isEqualTo: title)
.snapshots();
}
  • Document一覧を取得
1
2
3
4
5
Stream<QuerySnapshot> getGroupItem(String groupId) {
return Firestore.instance
.collection("group")
.getDocuments();
}
  • Documentを取得
1
2
3
4
5
6
7
8
Future getData(String collection, String documentId) async {
DocumentSnapshot docSnapshot =
await Firestore.instance
.collection(collection)
.document(documentId)
.get();
return docSnapshot.data;
}

データ削除

1
2
3
4
5
6
Future<void> removeImage(String groupId) {
return Firestore.instance
.collection("group")
.document(groupId)
.delete();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 Future<void> removeImage(String groupId, String groupDetailId) {
return Firestore.instance
.collection("group")
.document(groupId)
.collection("group_item")
.document(groupDetailId)
.delete();
}
```

### データ有無チェック

```dart
Query colRef = Firestore.instance
.collection('user')
.where('mobile', isEqualTo:_phoneNumber)
.where('type',isEqualTo:'editor');

colRef.getDocuments().then((data){
if(data.documents.isNotEmpty){
data.documents.forEach((data){
print(data['Name']);
});
Toast.show("authorize User", context,
duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);
} else{
Toast.show("Unauthorize User", context,
duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);
}
});

collection と document の違い

データ構造

collection

  • documentの集まり
  • Collection.get()で、documentの集まりを取得
  • 返ってくるオブジェクトは、QuerySnapshot
  • データへのアクセスは、QuerySnapshot.documents[0].data()

document

  • dataの集まり
  • Document.get()で、dataの集まりを取得
  • 返ってくるオブジェクトは、DocumentSnapshot
  • データへのアクセスは、DocumentSnapshot.data()

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

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

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

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

非同期でデータ取得後にウィジェットを表示する

参照先

Flutterで非同期でWidgetを生成する

非同期でデータを取得

1
2
3
Future<DocumentSnapshot> getUserInfo(String uid) {
return Firestore.instance.collection("user").document(uid).get();
}

非同期でデータを取得できたら、ウィジェットに表示する

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Widget _userImage(DocumentSnapshot data) {
return FutureBuilder(
// future属性で非同期処理を書く
future: chatHelper.getUserInfo(data.data["uid"]),
builder: (context, snapshot) {
// 取得完了するまで別のWidgetを表示する
if (!snapshot.hasData)
return CircleAvatar(
backgroundImage: AssetImage("assets/defaultImage.png"),
);

// 取得できたらそれにしたがってViewを表示する
return CircleAvatar(
backgroundImage: snapshot.data["profile_url"] == null
? AssetImage("assets/defaultImage.png")
: NetworkImage(snapshot.data["profile_url"]),
);
},
);
}

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();
}
},
),
Your browser is out-of-date!

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

×