Skip to content

Riverpod Providers

市场层的所有 Riverpod provider 集中在 lib/core/market/market_providers.dart。手动声明(无 codegen),风格和 lib/core/providers.dart 一致。

final marketConfigProvider = Provider<MarketConfig>(
(ref) => MarketConfig.defaultConfig,
);

市场配置。默认指向官方仓库。要指向自己的 fork,在 ProviderScope 里 override:

ProviderScope(
overrides: [
marketConfigProvider.overrideWithValue(
const MarketConfig(owner: 'my-org', repo: 'my-market', branch: 'main'),
),
],
child: const MoodPetApp(),
)
final marketCacheProvider = FutureProvider<MarketCache>((ref) async {
final support = await getApplicationSupportDirectory();
final root = Directory('${support.path}/moodpet/market-cache');
return MarketCache(root);
});

磁盘缓存单例。根目录 <appSupportDir>/moodpet/market-cache/。

final marketRepositoryProvider = FutureProvider<MarketRepository>((ref) async {
final config = ref.watch(marketConfigProvider);
final cache = await ref.watch(marketCacheProvider.future);
return MarketRepository(config, cache);
});

仓库单例。依赖 config 和 cache。

final pluginInstallerProvider = FutureProvider<PluginInstaller>((ref) async {
final repository = await ref.watch(marketRepositoryProvider.future);
return PluginInstaller(repository);
});

安装器单例。

final updateCheckerProvider = FutureProvider<UpdateChecker>((ref) async {
final repository = await ref.watch(marketRepositoryProvider.future);
final manager = await ref.watch(pluginManagerProvider.future);
return UpdateChecker(repository, manager);
});

更新检查器单例。依赖仓库和 pluginManagerProvider(来自 providers.dart)。

三个目录列表 provider,UI watch 它们渲染 Tab:

final marketFriendListProvider = FutureProvider<List<MarketPlugin>>((ref) async {
final repo = await ref.watch(marketRepositoryProvider.future);
return repo.listDirectory(MarketDir.friend);
});
final marketApplicationListProvider = FutureProvider<List<MarketPlugin>>((ref) async {
final repo = await ref.watch(marketRepositoryProvider.future);
return repo.listDirectory(MarketDir.application);
});
final marketPacksListProvider = FutureProvider<List<MarketPlugin>>((ref) async {
final repo = await ref.watch(marketRepositoryProvider.future);
return repo.listDirectory(MarketDir.packs);
});
final marketUpdatesProvider = FutureProvider<List<PluginUpdate>>((ref) async {
final checker = await ref.watch(updateCheckerProvider.future);
return checker.checkAll();
});

可用更新列表。UI watch 它决定是否显示红点。

final friendsAsync = ref.watch(marketFriendListProvider);
friendsAsync.when(
loading: () => const Center(child: CircularProgressIndicator()),
error: (e, _) => Center(child: Text('加载失败: $e')),
data: (friends) => GridView.builder(
itemCount: friends.length,
itemBuilder: (context, i) => MarketPluginCard(plugin: friends[i]),
),
);
// 刷新一个目录
ref.invalidate(marketFriendListProvider);
// 刷新所有
ref.invalidate(marketFriendListProvider);
ref.invalidate(marketApplicationListProvider);
ref.invalidate(marketPacksListProvider);
ref.invalidate(marketUpdatesProvider);

invalidate 会清掉 provider 的缓存值,下次 watch 时重新执行——走 MarketRepository.listDirectory,先查 MarketCache(5 分钟 TTL),未命中才走网络。

下拉刷新用 ref.refresh(provider.future):

RefreshIndicator(
onRefresh: () => ref.refresh(marketFriendListProvider.future).then((_) {}),
child: ...,
)

安装/更新成功后刷新 pluginManagerProvider(让新插件出现在已安装列表)和 marketUpdatesProvider(更新红点):

final result = await installer.install(plugin);
if (result.success) {
ref.invalidate(pluginManagerProvider);
ref.invalidate(marketUpdatesProvider);
}
final manager = ref.watch(pluginManagerProvider).maybeWhen(
data: (m) => m,
orElse: () => null,
);
final isInstalled = manager?.pluginById(plugin.id) != null;
final updatableIds = ref.watch(marketUpdatesProvider).maybeWhen(
data: (updates) => updates.map((u) => u.pluginId).toSet(),
orElse: () => const <String>{},
);
final isUpdatable = isInstalled && updatableIds.contains(plugin.id);

卡片三态:未安装 → “安装”;已安装有更新 → “更新”;已安装无更新 → “已安装”。