添付ファイルのリストをアップロードし、各要素が繰り返されるたびに各要素のステータスを更新しようとしています。アップロードが正常に完了した場合は、uploadSucceded = true、それ以外の場合は false を出力します。
Future<void> uploadAttachments() async {
int uploadableAttachmentIndex = 0;
emit(state.copyWith(isUploadingAttachments: true));
final attachments = generateFormAttachmentList();
await Future.forEach(
attachments,
(UploadableAttachment attachment) async {
final success = await uploadFile(attachment);
if (success) {
debugPrint('SUCCESS!!!!!');
emit(state.copyWith(
uploadableAttachments: state.uploadableAttachments!
..[uploadableAttachmentIndex].uploadSucceded = true,
));
} else {
debugPrint('FAILED!!!');
emit(state.copyWith(
uploadableAttachments: state.uploadableAttachments!
..[uploadableAttachmentIndex].uploadSucceded = false,
isUpdatingTask: false,
taskUpdateError: 'Error uploading attachment',
attachmentUploadsFailed: true));
}
uploadableAttachmentIndex++;
}
);
emit(state.copyWith(isUploadingAttachments: false));
}
値が設定されている間、関数の最後に発行するまで再構築はトリガーされず、アップロードのステータスが一度に再構築されます。forEach 内の再構築がトリガーされない理由はわかりませんが、問題はこの関数にあると思います。ブロック ビルダーは次のようになります。
class _UploadAttachmentsPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<TaskDetailsCubit, TaskDetailsState>(builder: (context, state) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
state.attachmentUploadsFailed
? _UploadErrorWidget()
: _UploadPageHeader(state.isUploadingAttachments),
SizedBox(height: 40),
Expanded(
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: state.uploadableAttachments!.length,
itemBuilder: (context, index) {
return _UploadProgressListItem(file: state.uploadableAttachments![index]);
},
),
),
],
);
});
}
}
uploadSucceded が設定されると、UploadProgressListItem が再構築されます。
class _UploadProgressListItem extends StatelessWidget {
final UploadableAttachment file;
_UploadProgressListItem({required this.file});
Widget getListTileIcon() {
if (file.uploadSucceded == true)
return Icon(Icons.check, color: CoreTheme.green);
else if (file.uploadSucceded == false)
return Icon(Icons.error, color: CoreTheme.error);
else
return CircularProgressIndicator();
}
Widget getSubtitle() {
if (file.uploadSucceded == true)
return Text(
'Complete',
style: CoreTheme.textStyleLabel(color: FontColor.green),
);
else if (file.uploadSucceded == false)
return Text(
'Problem Uploading',
style: CoreTheme.textStyleLabel(color: FontColor.red),
);
else
return Text('Uploading', style: CoreTheme.textStyleLabel());
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(14.0),
child: ListTile(
leading: getListTileIcon(),
title: Text(
file.filename,
overflow: TextOverflow.ellipsis,
style: CoreTheme.textStyleBodyRegular(),
),
subtitle: getSubtitle(),
),
);
}
}
class UploadableAttachment {
bool? uploadSucceded;
final File file;
final String filename;
final String fieldKey;
UploadableAttachment({
this.uploadSucceded,
required this.file,
required this.filename,
required this.fieldKey,
});
}
私は間違った非同期ルートを取っているのではないかと思っています。リストの代わりにストリームを使用する必要がありますか? BlocBuilder の代わりに BlocListener または BlocConsumer を使用する必要がありますか?