我很难理解为什么 Riverpod 和 Hook 的 UI 不刷新,尤其是在使用
HookConsumerWidget
和 ProviderFamily
传递一个参数时。
一些精度:
MediaThumbnail
由MediaThumbnailAPI
调用,并为其设置了唯一的键,MediaThumbnailAPI
位于gridviewbuilder内部(gridviewbuilder内的项目可以独立重建而不重建整个gridview吗?我认为这是可能的) .
我的理解是,当长按时, bool
isFavorite = ref.watch(favoriteFamilyProvider(id)).isMediaFavorite(id);
不会触发 setState
(相当于 Riverpod 钩子),但我不知道我的语法中缺少什么。
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import '../../../../favorite_provider.dart';
import 'package:universal_io/io.dart' as universal_io;
class MediaThumbnail extends HookConsumerWidget {
final String id;
final String fileExtension;
final universal_io.File imageFile;
final String urlEndpoint;
final String description;
final double thumbnailRadius;
final String mimeType;
const MediaThumbnail(this.imageFile, this.urlEndpoint, this.id,
this.fileExtension, this.description, this.thumbnailRadius, this.mimeType,
{Key? key})
: super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
bool isFavorite = ref.watch(favoriteFamilyProvider(id)).isMediaFavorite(id); // probably the problematic line of code.
return GestureDetector(
behavior: HitTestBehavior.translucent,
onLongPress: () {
ref.read(favoriteProvider.notifier)
.toggleFav(id, fileExtension, description); // this one works successfully and change the content of imageMetadataBox
isFavorite = ref.read(favoriteFamilyProvider(id)).isMediaFavorite(id); // the isFavorite value is correctly updated
print("is favorite: $isFavorite");
},
child: Stack(children: [
Container(
constraints: const BoxConstraints.expand(),
decoration: BoxDecoration(
image: DecorationImage(
image: FileImage(imageFile), fit: BoxFit.cover),
)),
if (isFavorite) // this does not refresh
Positioned(
top: 5,
left: 60,
right: .0,
child: Center(
child: Stack(
children: [
_buildIcon(16, Colors.white),
_buildIcon(13, Colors.pinkAccent),
],
),
),
)
]));
}
}
favorite_provider.dart
final favoriteFamilyProvider =
Provider.family<FavoriteFamilyNotifier, String>(
(_, myId) => FavoriteFamilyNotifier(myId));
class FavoriteFamilyNotifier extends StateNotifier<bool> {
FavoriteFamilyNotifier(String myId) : super(false) {}
bool isMediaFavorite(String myId) {
Store store = objectbox.store;
Box<MediaMetadata> imageMetadataBox = store.box<MediaMetadata>();
final qBuilder =
imageMetadataBox.query(MediaMetadata_.myId.equals(myId));
final query = qBuilder.build();
var results = query.find();
bool isFavorite = results.isNotEmpty;
print("$myId is favorite? $isFavorite");
return isFavorite;
}
非常感谢那些对这个库有经验的人。
注意:我使用“myId”是因为ObjectBox为其内部数据库保留了“id”关键字,因此
MediaMetadata_.myId
就像一个32长的字符串,而MediaMetadata_.id
是一个无符号整数。
您的问题似乎是您正在使用
Provider
来实现扩展 StateNotifier
的类。要解决此问题,请将 Provider
更改为 StateNotifierProvider
。
我还想指出
StateNotifier
是一种已弃用的做法。使用 Notifier
来实现您的 FavoriteFamilyNotifier
。
在
myId
方法中使用 isMediaFavorite()
字段似乎也更符合逻辑,您在创建 FavoriteFamilyNotifier(myId)
时将其作为字段传递。 或者去掉.family
,因为如果你用FavoriteFamilyNotifier(String myId)
创建一个类,然后根本不使用该字段,那么根本不清楚它扮演什么角色。
并且不太清楚为什么使用
HookConsumerWidget
,在本示例中的小部件内部没有使用它。