You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Riverpod:如何用搜索结果更新UI

问题:如何在Riverpod中切换FutureProvider数据源填充ListView

我正在使用名为defaultProvider的FutureProvider,通过ref.watch(defaultProvider)从API获取数据并填充ListView.Builder,代码如下:

ref.watch(countryProvider).when(
  data: (userData) {
    List<Article> itemList= userData.map((e) => e).toList();
    return <Widget>(// 这里使用itemList[index].data )
  },
  error:(){},
  loading(){}
)

我希望用另一个FutureProvider——ref.read(searchProvider(value))返回的搜索结果重新填充该视图,两者均返回List<CustomType>类型。应用加载时显示defaultProvider的数据,搜索后替换为搜索结果,该如何实现?

附defaultProvider代码:

final defaultProvider= FutureProvider<List<CustomType>>((ref) =>
    APIService(('queryparam', 'value'), apiUrl: URLConstants().urlType)
        .getData());

解决方案

核心思路是通过状态跟踪当前数据源类型,再动态选择对应的FutureProvider,以下是两种可行实现方式:

方案一:用状态Provider切换数据源

  1. 定义状态Provider记录搜索状态(null表示显示默认数据):
final searchStateProvider = StateProvider<String?>((ref) => null);
  1. 将搜索Provider改为家族Provider,接收搜索关键词参数:
final searchProvider = FutureProvider.family<List<CustomType>, String>((ref, query) =>
    APIService(('search', query), apiUrl: URLConstants().searchUrl)
        .getData());
  1. UI层根据搜索状态动态选择要监听的Provider:
@override
Widget build(BuildContext context, WidgetRef ref) {
  final searchQuery = ref.watch(searchStateProvider);
  
  // 根据搜索状态切换数据源
  final asyncData = searchQuery != null
      ? ref.watch(searchProvider(searchQuery))
      : ref.watch(defaultProvider);
  
  return asyncData.when(
    data: (dataList) {
      return ListView.builder(
        itemCount: dataList.length,
        itemBuilder: (context, index) {
          // 这里用dataList[index]渲染列表项
          return ListTile(title: Text(dataList[index].title));
        },
      );
    },
    error: (error, stackTrace) => Text('加载失败:$error'),
    loading: () => const CircularProgressIndicator(),
  );
}
  1. 触发搜索/清空搜索的逻辑:
// 执行搜索
void onSearch(String query) {
  ref.read(searchStateProvider.notifier).state = query;
}

// 回到默认数据
void clearSearch() {
  ref.read(searchStateProvider.notifier).state = null;
}

方案二:合并逻辑到单个FutureProvider

如果不想维护额外状态,可将默认数据与搜索数据的逻辑合并到一个家族Provider中:

final contentProvider = FutureProvider.family<List<CustomType>, String?>((ref, searchQuery) async {
  if (searchQuery != null && searchQuery.isNotEmpty) {
    // 返回搜索结果
    return APIService(('search', searchQuery), apiUrl: URLConstants().searchUrl).getData();
  } else {
    // 返回默认数据
    return APIService(('queryparam', 'value'), apiUrl: URLConstants().urlType).getData();
  }
});

UI层直接监听这个合并后的Provider,搭配状态保存搜索关键词:

final searchQueryProvider = StateProvider<String?>((ref) => null);

@override
Widget build(BuildContext context, WidgetRef ref) {
  final searchQuery = ref.watch(searchQueryProvider);
  final asyncData = ref.watch(contentProvider(searchQuery));
  
  return asyncData.when(
    data: (dataList) => ListView.builder(...),
    error: (e, s) => Text('出错了:$e'),
    loading: () => const CircularProgressIndicator(),
  );
}

触发搜索时更新searchQueryProvider的状态即可。


内容的提问来源于stack exchange,提问作者Ae Ri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 22:55:00