#flutter #flutter-provider #imagepicker #flutter-state #flutter-change-notifier
#flutter #flutter-provider #imagepicker #состояние флаттера #flutter-изменение-уведомление
Вопрос:
Я использую Image Picker
плагин Flutter, чтобы позволить пользователю изменять свой аватар. Когда пользователи переходят на страницу своей учетной записи, они видят свою обычную фотографию аватара со значком камеры сверху. Щелчок по значку камеры позволит им либо сделать снимок со своей камеры, либо выбрать новый аватар из своей галереи. После выбора нового фото аватара автоматически обновляется. Однако при переходе со страницы их учетной записи старый аватар отображается в остальной части приложения. Я использую Provider
с Change Notifier
и Consumers
для аватаров везде. Проблема в том, что я могу получить доступ только Provider
к сборке, поэтому я не знаю, где я могу вызвать Provider
в своем коде. Добавьте к этому тот факт, что аватар, который я использую во всем приложении, поступает с интернет-адреса. После выбора с помощью выбора изображения новая фотография аватара загружается на сервер. Название новой фотографии заменяет название старой фотографии. Следовательно, мое приложение даже не знает, что что-то изменилось. Даже перезагрузка страниц не работает. Однако, если я перезапущу свое приложение, появится новая фотография аватара. Есть идеи, что я могу сделать?
Вот код выбора изображения;
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.phpamp;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();
}
}
Итак, я попытался поместить это в my Provider
и вызвать его из функции onTap в сборке средства выбора изображений. Вот функция 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-адрес для аватара не изменился, поскольку фотография просто была заменена и сохранила то же имя.
Комментарии:
1. где код модели поставщика?
2. Поскольку вы помещаете выбранный аватар в поле улья, вы можете вызывать
get
ссылку на поле везде, где вам нужно изображение.3. Если вы вызываете
openBox
что-то вроде inmain
, то в остальной части приложения вы можете использоватьbox
метод для извлечения поля.box()
это вызов синхронизации.4. Чтобы открыть окно синхронно, вы должны использовать
Hive.box('boxName')
.5. В улье есть ValueListenableBuilder
Ответ №1:
Использование прослушивателя Hive было хорошей идеей. Но это не помогло, потому что оказалось, что загруженное изображение, имеющее тот же URL, что и замененное изображение, не обновляется на стороне сервера. Таким образом, кэширование должно быть отсортировано на веб-сервере.