提供者 NotifyListeners 不更新消费者
Posted
技术标签:
【中文标题】提供者 NotifyListeners 不更新消费者【英文标题】:Provider NotifyListeners not updating consumers 【发布时间】:2021-03-17 16:47:30 【问题描述】:我是 Flutter 的新手,真的非常想使用 provider 来传递数据,但我就是无法让它工作。我想我一切都设置好了,但由于某种原因,当我通知听众时,我的应用程序没有刷新。我要做的就是更新个人资料图片。我从 firebase 中的图片开始(工作正常)。然后我让用户可以选择用相机或照片更新他们的照片。当他们选择一张新照片时,消费者不会像我期望的那样更新。有人可以告诉我我是否做错了什么或者我如何能够做到这一点?
首先,这是我的主要内容:
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MultiProvider(
providers: [
ChangeNotifierProvider<Storage>(create: (context) => Storage()),
StreamProvider<Uid>.value(value: AuthService().user),
],
child: MaterialApp( ....
然后这里是更新我从图像选择器类调用的照片 URL 的类和方法。我正在传递上下文,因此我可以弹出该图像选择器视图并在完成后返回个人资料页面。
class Storage with ChangeNotifier
String userPhotoUrl;
void uploadImage(PickedFile _imageFile, BuildContext context) async
.... //some other code here
try
var snapshot =
await _storage.ref().child('/profileImages/$_userId').putFile(file);
await snapshot.ref.getDownloadURL().then((value)
userPhotoUrl = value;
notifyListeners();
print(userPhotoUrl); //I know the code is working because it prints here
Navigator.pop(context);
);
catch (e)
print(e);
这是我正在尝试更新的个人资料页面。它只是没有得到更新的值。
class Profile extends StatefulWidget
Profile(Key key) : super(key: key);
@override
_ProfileState createState() => _ProfileState();
/// This is the private State class that goes with MyStatefulWidget.
class _ProfileState extends State<Profile> with TickerProviderStateMixin
String imageUrl; //firebase pic to start - works fine
@override
Widget build(BuildContext context)
....//some more widget tree
Consumer<Storage>(
builder: (context, storage, widget) =>
CircularProfileAvatar( //never updates. userPhotoURL always null
storage.userPhotoUrl ?? imageUrl, //always uses imageUrl,
elevation: 20,
borderColor: Colors.white70,
borderWidth: 1,
radius: 50,
),
),
知道为什么它不起作用吗?我认为这应该很容易,但提供者仍在暗指我......
【问题讨论】:
class Storage with ChangeNotifier
应该是 class Storage extends ChangeNotifier
你是如何从视图中触发uploadImage()
的
@Toheeb,感谢您的建议,但扩展 ChangeNotifier 并没有帮助。我使用'with'是因为我最初扩展了存储,然后删除了扩展并忘记了更改。 uploadImage() 是从 ImageGrabber 类中调用的。所以流程是,用户在个人资料页面上,然后单击一个按钮,将他们带到 ImageGrabber 页面以选择相机或照片。然后有一个上传按钮,它从 Storage 调用 uploadImage()。我正在传递上下文以弹出 ImageGrabber 视图并返回到 Profile。
您是否在做类似var storageNotifier = Provider.of<Storage>(context);
的事情,然后像storageNotifier.uploadImage()
这样触发上传?
不,我使用 provider 只是为了获取 imageUrl,然后当 Provider.of 不起作用时,我转而尝试 Consumer,但同样的事情。我正在使用来自不同类的按钮来调用 uploadImage()。
【参考方案1】:
你使用了错误的方法来解决你需要做一些这样的问题
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChangeNotifierProvider<Storage>(
create: (context) => Storage(),
child: ImageGrabberScreen(),
),
),
);
导航到您要使用Consumer()
小部件的屏幕时
通过使用 Provider 或 MultipleProvider 作为父级,你告诉颤振你想使用 StreamBuilder()
widget 但从你的工作中我看到你正在使用 Consumer()
小部件
还可以尝试执行以下操作来触发您的功能
Widget build(BuildContext context)
var storageNotifier = Provider.of<Storage>(context);
///In your button you can then do storageNotifier.uploadImage();
如果您没有用于触发此事件的任何形式的按钮,最好使用FutureBuilder
解决此类问题
Future<String> uploadImage() async
.... //some other code here
var snapshot =
await _storage.ref().child('/profileImages/$_userId').putFile(file);
return await snapshot.ref.getDownloadURL();
然后在小部件树的某个地方执行此操作
FutureBuilder(
future: uploadImage(),
builder: (_,snapshot)
if(snapshot.hasData)
return CircularProfileAvatar(snapshot.data);
else
return CircularProfileAvatar(imageUrl);
)
...widget tree continues
【讨论】:
这并没有改变结果。它仍然像以前一样工作。不过感谢您的建议。还有什么? 理想情况下,您应该使用FutureBuilder
来解决这个问题,我会更新我的答案。
我喜欢 FutureBuilder 的建议,初始按钮首先将我带到不同的视图/类 (ImageGrabber)。在 imageGrabber 中,还有另一个按钮可以使用触发 uploadImage() 的图片。那么你会建议我如何使用 FutureBuilder 来完成这项工作?以上是关于提供者 NotifyListeners 不更新消费者的主要内容,如果未能解决你的问题,请参考以下文章
Flutter:`notifyListeners`不更新列表
Provider 调用 notifyListeners() 时 Flutter View 不更新视图