はじめに
前回はFlutter Widget of the Weekの「#11 SliverAppBar」、「#12 SliverList & SliverGrid」を紹介しました。
今回はその続きで「#13 FadeInImage」、「#14 StreamBuilder」の2つです。
前回の記事はこちら
Flutter Widget of the Week
環境
- Flutter 2.8.1
記事にした時点でのバージョンです。GitHubに公開しているのは常に最新の安定版(stable)を使う予定です。
#13 FadeInImage
FadeInImageとは
画像をURLからダウンロードして表示する際に、ダウンロードが終わるまでの間プレースホルダとして何かしらの画像を表示したい場合に、このFadeInImageのウィジェットを使います。
サンプルコード
import 'package:flutter/material.dart';
class SamplePage013 extends StatelessWidget {
const SamplePage013({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('FadeInImage'),
),
body: SafeArea(
child: Center(
child: FadeInImage.assetNetwork(
placeholder: 'assets/sample.png',
image:
'https://upload.wikimedia.org/wikipedia/commons/thumb/4/44/Google-flutter-logo.svg/440px-Google-flutter-logo.svg.png',
height: 50,
),
),
),
);
}
}
結果
初期状態ではアプリ内の画像が表示されていますが、
通信が終了するとアプリ内の画像がフェード・アウトし、URLの画像がフェードインしてきました。
動画
公式リファレンス
FadeInImage class - widgets library - Dart API
API docs for the FadeInImage class from the widgets library, for the Dart programming language.
#14 StreamBuilder
StreamBuilderとは
非同期のデータストリームをウィジェットで使いたい場合にこのStreamBuilderを使います。
データストリームに変更があった場合に、StreamBuilder内のbuilder内を再ビルドしてくれます。
StreamBuilderを使う場合は、データの存在を確認できるhasDataや、エラーがあるかどうかのhasErrorは実装しておいたほうが良いです。
サンプルコード
import 'package:flutter/material.dart';
class SamplePage014 extends StatefulWidget {
const SamplePage014({
Key? key,
}) : super(key: key);
@override
_SamplePage014State createState() => _SamplePage014State();
}
class _SamplePage014State extends State<SamplePage014> {
final Stream<String> _successStream = (() async* {
await Future<void>.delayed(const Duration(seconds: 1));
yield 'Success';
await Future<void>.delayed(const Duration(seconds: 1));
})();
final Stream<String> _errorStream = (() async* {
await Future<void>.delayed(const Duration(seconds: 1));
throw Exception('Error');
yield 'Success';
await Future<void>.delayed(const Duration(seconds: 1));
})();
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('#14 StreamBuilder'),
),
body: SafeArea(
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text('StreamBuilder Success'),
StreamBuilder<String>(
stream: _successStream,
builder: (context, snapshot) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
_samplePage014StreamWidget(snapshot),
_samplePage014StreamStateWidget(snapshot),
],
);
},
),
const SizedBox(height: 20),
const Text('StreamBuilder Error'),
StreamBuilder<String>(
stream: _errorStream,
builder: (context, snapshot) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
_samplePage014StreamWidget(snapshot),
_samplePage014StreamStateWidget(snapshot),
],
);
},
),
],
),
),
),
);
}
Widget _samplePage014StreamWidget(AsyncSnapshot<String> snapshot) {
if (snapshot.hasError) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(
Icons.error,
color: Colors.red,
),
Text(snapshot.error?.toString() ?? ''),
],
);
}
if (!snapshot.hasData) {
return const CircularProgressIndicator();
}
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(
Icons.check_circle,
color: Colors.green,
),
Text(snapshot.data ?? ''),
],
);
}
Widget _samplePage014StreamStateWidget(AsyncSnapshot<String> snapshot) {
var text = '';
switch (snapshot.connectionState) {
case ConnectionState.waiting:
text = 'waiting';
break;
case ConnectionState.none:
text = 'none';
break;
case ConnectionState.active:
text = 'active';
break;
case ConnectionState.done:
text = 'done';
break;
}
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(
Icons.info,
color: Colors.blue,
),
Text('status : $text'),
],
);
}
}
結果
最初はSuccess、Error両方とも読込中ですが
読み込みが完了するとSuccessとErrorに表示が切り替わりますが、Successは処理が終わっていないのでステータスがactiveのままです。
Successの処理が完了しました。
動画
公式リファレンス
StreamBuilder class - widgets library - Dart API
API docs for the StreamBuilder class from the widgets library, for the Dart programming language.
さいごに
FadeInImageは使い所がよくわからん。。。
おすすめ参考書
リンク
GitHub - nobushiueshi/flutter_widget_of_the_week
Contribute to nobushiueshi/flutter_widget_of_the_week development by creating an account on GitHub.
コメント