CONTENT
ここから
この章では、3Dモデルの読み込み状況を表す状態を定義します。
3Dモデルは、画面を開いた瞬間に表示されるとは限りません。インターネット上からファイルを取得し、解析して描画するまでに時間がかかります。また、通信環境やURLの問題によって読み込みに失敗する場合もあります。
そこで、現在の状況を一つの状態として管理し、後の章で状態に応じた表示へ切り替えられるようにします。
11.1 3Dモデル表示に必要な状態
今回のビューアーでは、次の3つの状態を扱います。
| 状態 | 意味 |
|---|---|
loading | 3Dモデルを読み込んでいる |
ready | 読み込みが完了し、操作できる |
error | 読み込みに失敗した |
アプリを起動した直後は、まだモデルが表示されていないためloadingです。正常に読み込まれればreadyへ変化し、失敗した場合はerrorへ変化します。
loading ──成功──▶ ready
│
└──失敗──▶ error
エラー後に再読み込みする場合は、errorから再びloadingへ戻します。
11.2 enumで状態を定義する
複数の決まった選択肢を表す場合は、Dartのenumを使用します。
model_viewer_screen.dartのimport文より下へ、次の定義を追加します。
enum ViewerStatus {
loading,
ready,
error,
}
ViewerStatusは、3Dビューアーの状態を表す独自の型です。この型の値には、定義した3種類以外を代入できません。
1行で記述することもできます。
enum ViewerStatus { loading, ready, error }
教材では意味を確認しやすいように複数行で記述しても、完成コードに合わせて1行で記述しても構いません。
11.3 状態を保持する変数を追加する
_ModelViewerScreenStateの中へ、現在の状態を保持するフィールドを追加します。
class _ModelViewerScreenState extends State<ModelViewerScreen> {
final Flutter3DController _controller = Flutter3DController();
ViewerStatus _status = ViewerStatus.loading;
}
アプリ起動時にはモデルの読み込みが完了していないため、初期値をViewerStatus.loadingにします。
変数名の先頭にある_は、このファイルの外部へ公開しない値であることを示します。
11.4 真偽値ではなくenumを使う理由
状態を真偽値で管理する方法もあります。
bool _isLoading = true;
bool _isReady = false;
bool _hasError = false;
しかし、この方法では次のような矛盾が発生する可能性があります。
_isLoading = true;
_isReady = true;
_hasError = true;
これでは、読み込み中、完了、エラーのすべてが同時に成立しています。どの表示を優先すべきか判断できません。
enumを使用すると、_statusが保持できる値は常に一つです。
_status = ViewerStatus.loading;
または、次のどちらかです。
_status = ViewerStatus.ready;
_status = ViewerStatus.error;
状態の組み合わせを考える必要がなくなり、処理の流れを読みやすくできます。
11.5 エラーメッセージを保持する
errorという状態だけでは、何が原因で失敗したのか利用者へ伝えられません。そこで、パッケージから受け取ったエラー内容を保持する文字列も追加します。
String _errorMessage = '';
状態とエラーメッセージは、役割が異なります。
_status:現在どの状態にあるか_errorMessage:失敗した理由として表示する内容
読み込み中と完了時にはエラー内容が不要なため、初期値は空文字列にします。
class _ModelViewerScreenState extends State<ModelViewerScreen> {
final Flutter3DController _controller = Flutter3DController();
ViewerStatus _status = ViewerStatus.loading;
String _errorMessage = '';
}
11.6 状態を変更する方法
状態を変更するときは、前章で学んだsetState()を使用します。
読み込みが完了した場合は、次のように更新します。
setState(() {
_status = ViewerStatus.ready;
_errorMessage = '';
});
読み込みに失敗した場合は、状態とエラーメッセージを同時に変更します。
setState(() {
_status = ViewerStatus.error;
_errorMessage = error;
});
再読み込みを開始するときは、状態をloadingへ戻し、以前のエラーを削除します。
setState(() {
_status = ViewerStatus.loading;
_errorMessage = '';
});
関連する値を同じsetState()内で変更すると、状態と表示内容の不一致を防げます。
11.7 状態遷移を整理する
このアプリで想定する状態遷移は、次のとおりです。
アプリ起動
↓
ViewerStatus.loading
├─ 読み込み成功 → ViewerStatus.ready
└─ 読み込み失敗 → ViewerStatus.error
↓
再読み込み
↓
ViewerStatus.loading
readyになった後でも、ビューアーを再生成すれば再びloadingへ戻ります。
状態遷移を事前に整理しておくと、どのイベントで何を更新するべきかが明確になります。
11.8 この章で追加するコード
この章では、model_viewer_screen.dartの先頭付近にViewerStatusを追加します。
import 'package:flutter/material.dart';
import 'package:flutter_3d_controller/flutter_3d_controller.dart';
import 'package:flutter_3d_model_viewer/config/model_source.dart';
/// 3Dビューアーの現在の読み込み状態です。
enum ViewerStatus {
loading,
ready,
error,
}
続いて、Stateクラスへ状態変数を追加します。
class _ModelViewerScreenState extends State<ModelViewerScreen> {
final Flutter3DController _controller = Flutter3DController();
ViewerStatus _status = ViewerStatus.loading;
String _errorMessage = '';
// 既存のbuildメソッドはこの下に残します。
}
現時点では、状態を追加しても画面表示は変わりません。次章で3Dビューアーから読み込みイベントを受け取り、実際に状態を更新します。
11.9 この章の到達目標
この章の終了時点で、次の内容を確認します。
- 読み込み中、完了、エラーの3状態を説明できる
enumを使って決まった状態を定義できる- 状態変数へ初期値を設定できる
- 複数の
boolで管理する場合の問題を説明できる - 状態とエラーメッセージの役割を区別できる
- 3Dビューアーの状態遷移を説明できる
次章では、
onProgress、onLoad、onErrorを使い、3Dモデルの読み込み状況を画面状態へ反映します。