はじめに
Kotlinのsealed classはこんな感じで書けますね。
sealed class SampleResultModel {
data class Success(val value: String) : SampleResultModel()
object Error : SampleResultModel()
}
これをDartで表現したいとき、Dartの言語機能にこのようなことを表現できる機能がまだ備わっていないためfreezedというパッケージを使って表現します。
https://pub.dev/packages/freezed
本編
freezedを使って先程のKoltinのsealed classを表現すると以下のよう書き方をします。
@freezed
class SampleResultModel with _$SampleResultModel {
const factory SampleResultModel.success({
required String value,
}) = SampleSuccess;
const factory SampleResultModel.failure() =
SampleFailure;
}
使うときはこんな感じで、usecaseなどでdatasourceにアクセスして結果に応じてそれぞれのfactoryを呼んでResultModelを返すことができます。
Future<SampleResultModel> call() async {
try {
final response = await _sampleDataSource.fetchSomeThing();
return SampleResultModel.success(
value: response.value,
);
} on DioError catch (e) {
if (e.type == DioErrorType.response && e.response != null) {
return const SampleResultModel.failure();
}
}
}
更に、DioErrorをcatchすればstatusCodeに応じて各factoryを呼んでResultModelを返すこともでき何のエラーだったのかを判別してUIなどに伝えることができるようになります。
Future<SampleResultModel> call() async {
try {
final response = await _sampleDataSource.fetchSomeThing();
return SampleResultModel.success(
value: response.value,
);
} on DioError catch (e) {
if (e.type == DioErrorType.response && e.response != null) {
switch (e.response!.statusCode) {
case HttpStatus.preconditionFailed: // 412
// このケースのreturn
case HttpStatus.forbidden: // 403
// このケースのreturn
case HttpStatus.badRequest: // 400
// このケースのreturn
}
}
}
}
UIなどでは受け取ったmodelに対してwhenメソッドがfreezed側で自動生成されてるのでそれを使って成功時はコンテンツを表示して失敗時はSnackbarを出したりなどできるようになります。
model.when(
success: (value) {
// 成功時にvalueを使ってなにかUI表示する
},
failure: () {
// 失敗時はSnackbar表示する
},
);