Flutter MobX Observer does not fire upon @action

2,554

Okay, seems that this part

@observable
List<File> images = [];

does not work (currently?)

Replacing it with

final images = ObservableList<File>.of([]);

will yield the wanted results

Share:
2,554
Rhywden
Author by

Rhywden

Updated on December 17, 2022

Comments

  • Rhywden
    Rhywden over 1 year

    I'm using a MultiProvider which wraps my whole app. I'm already using another Store/Observer for authentication/login and that part works as it should. I just added another store which reflects the photos a user has taken and which then get displayed at two different places before uploading.

    The "taking the photo" and "insert them into the store" works fine. The part which is then supposed to reactively display the photos... not so much.

    Relevant code:

    import 'dart:io';
    
    import 'package:mobx/mobx.dart';
    import 'package:image_picker/image_picker.dart';
    
    part 'photoview_store.g.dart';
    
    class PhotoviewStore = _PhotoviewStore with _$PhotoviewStore;
    
    abstract class _PhotoviewStore with Store {
      @observable
      List<File> images = [];
    
      @computed
      int get length => images.length;
    
      @action
      Future getImage({bool fromGallery: true}) async {
        ImageSource source = fromGallery ? ImageSource.gallery : ImageSource.camera;
        File _image;
        try {
          _image = await ImagePicker.pickImage(source: source);
          if(images.length >= 3) images.removeLast();
          images.insert(0, _image);
          print('New length: ${images.length}');
        } catch(_) {
          print('Error getting image');
        }
      }
    
      @action
      void removePicture(int index) {
        images.removeAt(index);
      }
    }
    

    The @computed I added because I thought it might be problematic to access images.length in the Observer. Doesn't do anything, though.

    class NeuesAnliegen extends StatefulWidget {
      @override
      _NeuesAnliegenState createState() => _NeuesAnliegenState();
    }
    
    class _NeuesAnliegenState extends State<NeuesAnliegen> with AutomaticKeepAliveClientMixin{
    [...]
    @override
      Widget build(BuildContext context) {
        final photoStore = Provider.of<PhotoviewStore>(context);
        super.build(context);
        [...]
           Row(
                    children: <Widget>[
                      Expanded(
                        flex: 1,
                        child: Observer(builder: (_) {
                          print(photoStore.length);
                          if(photoStore.length < 1) return Container();
                          return GestureDetector(
                            child: Image.file(photoStore.images[0], height: 100),
                            onTap: () { },
                          );
                        },)
                      ),
                      Expanded(
                        flex: 1,
                        child: Observer(builder: (_) {
                          if(photoStore.length < 2) return Container();
                          return GestureDetector(
                            child: Image.file(photoStore.images[1], height: 100),
                            onTap: () { },
                          );
                        },)
                      ),
                      Expanded(
                        flex: 1,
                        child: Observer(builder: (_) {
                          if(photoStore.length < 3) return Container();
                          return GestureDetector(
                            child: Image.file(photoStore.images[2], height: 100),
                            onTap: () { },
                          );
                        },)                  )
                    ],
                  ),
        [...]
                      Expanded(
                          child: RaisedButton.icon(
                            onPressed: () => photoStore.getImage(fromGallery: false,),
                            icon: Icon(Icons.camera),
                            label: Text('Foto aufnehmen')
                          ),
                        ),
    

    So, I can take a photo just fine and it does get added to the images list but the Observable never fires.