reorderables
reorderables copied to clipboard
Reordering when widget is rebuilding crashes
I'm using a ReorderableColumn. One of the widgets is a file upload component. On file save, the widget displays a circular progress indicator. If I drag the widget with the animation active, there are several errors. This is due to the widget being unmounted during drag.
Error: setState() called after dispose(): _FilePickerWidgetState#174b4(lifecycle state: defunct, not mounted)
Is it possible that the widget stays mounted, and there is only a visual animation of drag? Once the index's are available of the drag position we can swap the widgets. I also have move up/move down buttons, and these do not cause any issues.
The Flutter build-in ReorderableListView works - there are less controls available, but I no longer get any errors.
I'd still like to use Reorderables though if this issue can be fixed.
same issue here.
Flow:
- Pick images
- Display the selected images on ReorderableWrap
- Make an http request when image selected (on ImagePickerItem initState)
- Reorder the Wrap
Issue The issue is on step 4. While reordering, the ImagePickerItem rebuilding, calling again the initState
ReorderableWrap(
spacing: 8.0,
runSpacing: 4.0,
alignment: WrapAlignment.center,
padding: const EdgeInsets.all(8),
needsLongPressDraggable: false,
children: _selectedImages.map(
(imageFile) {
return ImagePickerItem(
key: ValueKey(imageFile.path),
image: imageFile,
);
},
).toList(),
onReorder: (oldIndex, newIndex) {
final File item = _selectedImages.removeAt(oldIndex);
_selectedImages.insert(newIndex, item);
if (!mounted) return;
setState(() {});
},
),
class ImagePickerItem extends StatefulWidget {
const ImagePickerItem({
super.key,
required this.image,
});
final File image;
@override
State<ImagePickerItem> createState() => _ImagePickerItemState();
}
class _ImagePickerItemState extends State<ImagePickerItem> {
bool isLoading = true;
@override
void initState() {
super.initState();
init();
}
@override
Widget build(BuildContext context) {
return Stack(
alignment: Alignment.center,
children: [
Card(
child: Padding(
padding: const EdgeInsets.all(4.0),
child:
Image.file(
widget.image,
height: 90,
),
),
),
if (isLoading)
const Positioned.fill(
child: Center(
child: CircularProgressIndicator.adaptive(),
),
),
],
);
}
init() async {
await Future.delayed(const Duration(seconds: 1));
if (mounted) {
setState(() {
isLoading = false;
});
}
}
}