Flutter / Dart - Как обновить изображение после средства выбора изображений на других экранах

Я использую плагин Flutter Image Picker, чтобы позволить пользователю изменять свой аватар. Когда они переходят на страницу своей учетной записи, они видят свою обычную фотографию аватара со значком камеры наверху. Щелчок по значку камеры позволит им сделать снимок со своей камеры или выбрать новый аватар из своей галереи. После выбора нового фото аватара автоматически обновится. Однако при уходе со страницы своей учетной записи старый аватар виден в остальной части приложения. Я использую Provider с Change Notifier и Consumers для аватаров везде. Однако проблема в том, что я могу получить доступ к Provider только внутри сборки, поэтому я не знаю, где я могу вызвать Provider в моем коде. Добавьте к этому тот факт, что аватар, который я использую во всем приложении, исходит из URL-адреса в Интернете. После выбора с помощью Image Picker новая фотография аватара загружается на сервер. Имя новой фотографии заменяет имя старой фотографии. Следовательно, мое приложение даже не знает, что что-то изменилось. Даже перезагрузка страниц не работает. Однако, если я перезапущу свое приложение в горячем режиме, появится новая фотография аватара. Есть идеи, что я могу сделать?

Вот код средства выбора изображения;

class Picker extends StatefulWidget {
  Picker({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _PickerState createState() =>  _PickerState();
}

class _PickerState extends State<Picker>
    with TickerProviderStateMixin,ImagePickerListener{

  File _image;
  AnimationController _controller;
  ImagePickerHandler imagePicker;

  @override
  void initState() {
    super.initState();
    _controller =  AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 500),
    );

    imagePicker= ImagePickerHandler(this,_controller);
    imagePicker.init();

  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    var socialProvider = Provider.of<SocialProvider>(context);
    return  Container(
      child:  GestureDetector(
        onTap: () => imagePicker.showDialog(context),
        child:  Center(
            child: Stack(
              children: <Widget>[
                Center(
                      child: _image == null?
                          Consumer<SocialProvider>(
                          builder: (context, socialProvider, child) {
                            return
                              Image.network(socialProvider.currentavatar,
                              width: 200,
                              height: 200,
                            );
                          }) :
                              Container(
                              height: 200.0,
                              width: 200.0,
                              decoration:  BoxDecoration(
                              color: Colors.grey,
                              image:  DecorationImage(
                              image:  FileImage(_image),
                              fit: BoxFit.cover,
                          ),                              
                        ),
                      ),
                ),

                Center(
                  child: ClipRRect(
                    borderRadius: BorderRadius.circular(20.0),
                    child: Container(
                      color: Colors.black26,
                      child: Icon(Icons.camera_alt,
                        color: Colors.white,
                        size: 40,
                      ),
                    ),
                  ),
                ),
               ,
            )
        ),
      ),
    );
  }

  @override
  userImage(File _image) async{
     setState(() {
      this._image = _image;
    });
  }
} 

В настоящее время Consumers правильно обновляют аватары во всем приложении всякий раз, когда пользователь получает новый аватар при входе в систему через социальные сети. Новый аватар будет загружен на сервер, и ChangeNotifier будет проинформирован. Код для Provider здесь:

Future<void> postSocialData(String avatar) async {
    final url = "http://example.com/example.php&currentavatar=" + $avatar;
    final response = await http.get(url);

    if (response.statusCode == 200) {
      currentavatar = "http://example.com/user.jpg";      
      var box = await Hive.openBox('currentuser');
      box.put('currentavatar', "http://example.com/user.jpg",);
      notifyListeners();    
    } 
  }

Поэтому я попытался поместить это в свой Provider и вызвать его из функции onTap в сборке Image Picker. Вот функция onTap;

GestureDetector(
                  onTap: () async  {
                       String avatar = await _listener.openGallery(socialProvider.currentuserid);
                       String updatedavatar = "http://example.com/" + avatar;
                       socialProvider.updateAvatar(updatedavatar);
                       },

                  child: roundedButton(
                      "Gallery",
                      EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0),
                      const Color(0xFF167F67),
                      const Color(0xFFFFFFFF)),
                ),

И вот Provider он вызывает;

Future<void> updateAvatar(String avatar) async {
     var box = await Hive.openBox('currentuser');
           box.put('currentavatar', avatar);
           currentavatar = avatar;
      notifyListeners();
   }

Но это не обновило потребителей с новым аватаром. Я предполагаю, потому что внешний URL-адрес аватара не изменился, поскольку фотография была просто заменена и сохранила то же имя.


comment
где код модели провайдера?   -  person Tirth Patel    schedule 07.10.2020
comment
Привет, Тирт, я только что отредактировал вопрос, включив в него код провайдера.   -  person Meggy    schedule 07.10.2020
comment
Поскольку вы помещаете выбранный аватар в Hive Box, вы можете вызвать get в ссылке на поле, где бы вам ни понадобилось изображение.   -  person Tirth Patel    schedule 07.10.2020
comment
Я добавил в сборку следующее, но при слове get выдает ошибку. Android Studio сообщает мне, что метод get не определен для метода Future. var box = Hive.openBox ('currentuser'); var boxbio = box.get ('currentbio');   -  person Meggy    schedule 07.10.2020
comment
Вы хотите сказать, что я должен поместить Hive get в свой провайдер, чтобы потребитель обновлял состояние при выборе изображения? Полагаю, мне тоже придется делать эту сборку в будущем?   -  person Meggy    schedule 08.10.2020
comment
Если вы вызываете openBox где-нибудь, как в main, то в остальной части приложения вы можете использовать метод box для извлечения поля. box() - это вызов синхронизации.   -  person Tirth Patel    schedule 08.10.2020
comment
У меня в основном есть следующее: void main () async {WidgetsFlutterBinding.ensureInitialized (); final appDocDir = ждать getApplicationDocumentsDirectory (); Hive.init (appDocDir.path); await Hive.initFlutter (); var box = await Hive.openBox ('currentuser'); runApp (Приложение ()); } Но невозможно синхронно открыть окно в моей сборке с помощью - box.get ('currentavatar') - слово get выделено красным. Есть ли шанс показать мне пример кода?   -  person Meggy    schedule 08.10.2020
comment
Чтобы открыть ящик синхронно, вы должны использовать Hive.box('boxName').   -  person Tirth Patel    schedule 08.10.2020
comment
Есть ли у Hive собственный слушатель, или я должен просто использовать его с Provider и ChangeNotifier, чтобы обновлять сборки везде, где требуется новый аватар?   -  person Meggy    schedule 08.10.2020
comment
У Hive есть ValueListenableBuilder.   -  person Tirth Patel    schedule 08.10.2020
comment
Я пробовал использовать небольшой плагин под названием HiveListener, но, похоже, он не обновляет аватары. Здесь я должен рассказать Флаттеру о новом аватаре? @override userImage (файл _image) {var box = Hive.box ('currentuser'); setState (() {box.put ('currentavatar', _image);}); }   -  person Meggy    schedule 08.10.2020


Ответы (1)


Использование слушателя Hive было хорошей идеей. Но это не помогло, потому что оказалось, что загруженное изображение, имеющее тот же URL, что и замененное изображение, не обновляется на стороне сервера. Так что с кешированием нужно разобраться на веб-сервере.

person Meggy    schedule 21.10.2020