更改 Riverpod 通知程序的状态后 UI 不会更新

问题描述 投票:0回答:1

我正在使用

SearchAnchor
SearchBar
,并且我正在尝试显示由 Google Places API(新)检索到的自动完成建议。 api 调用工作并返回结果及其解析。 UI 列表始终保持为空,尽管它刚刚收到
initialState []
。我需要改变什么?

我正在使用这个 Riverpod 通知程序

@riverpod
class QueryService extends _$QueryService {
  final initialState = <Suggestion>[];

  @override
  Future<List<Suggestion>> build() async {
    return initialState;
  }

  Future<void> searchForQuery(String query) async {
    if (query.isEmpty) {
      state = AsyncData(initialState);
    } else {
      final Position(:latitude, :longitude) = await ref.read(positionProvider.future);
      final data = jsonEncode({
        "input": query,
        "includeQueryPredictions": true,
        "locationBias": {
          "circle": {
            "center": {"latitude": latitude, "longitude": longitude},
          },
        },
      });
      final uri = Uri.https(_baseUrl, 'v1/places:autocomplete');
      final response = await http.post(uri, headers: _headers, body: data);
      final autocompleteResponse = AutocompleteResponse.fromJson(jsonDecode(response.body));
      state = AsyncData(autocompleteResponse.suggestions);
    }
  }
}

这是搜索锚代码

class MapSearchBar extends ConsumerStatefulWidget {
  const MapSearchBar({ super.key });

  @override
  ConsumerState<MapSearchBar> createState() => _MapSearchBarState();
}

class _MapSearchBarState extends ConsumerState<MapSearchBar> {
  final _searchController = SearchController();

  @override
  void initState() {
    super.initState();
    _searchController.addListener(() {
      ref.read(queryServiceProvider.notifier).searchForQuery(_searchController.text);
    });
  }

  @override
  Widget build(BuildContext context) {
    final suggestionsState = ref.watch(queryServiceProvider);

    return SearchAnchor(
      searchController: _searchController,
      viewBackgroundColor: kWhite,
      viewSurfaceTintColor: kWhite,
      dividerColor: kGrey,
      builder: (context, controller) => SearchBar(
        controller: controller,
        onChanged: (value) {
          controller.openView();
        },
      ),
      suggestionsBuilder: (context, controller) {
        if (!controller.isOpen) controller.openView();

        return suggestionsState.when(
          data: (suggestions) => suggestions.map((suggestion) {
            return ListTile(
              title: Text(suggestion.structuredFormat.mainText.text),
              onTap: () {},
            );
          }),
          error: (_, __) => [Text('error')],
          loading: () => [Text('loading')],
        );
      },
    );
  }
}

这也是冻结的模型

@freezed
class AutocompleteResponse with _$AutocompleteResponse {
  const factory AutocompleteResponse(@SuggestionConverter() List<Suggestion> suggestions) = AutocompleteResponseData;

  factory AutocompleteResponse.fromJson(Map<String, dynamic> json) => _$AutocompleteResponseFromJson(json);
}

@freezed
sealed class Suggestion with _$Suggestion {
  const factory Suggestion.place({
    required String place,
    required String placeId,
    required TextMatchData text,
    required StructuredFormatData structuredFormat,
    required List<PlaceType> types,
  }) = PlaceSuggestion;

  @SuggestionConverter()
  const factory Suggestion.query({
    required StructuredFormatData structuredFormat,
    required TextMatchData text,
  }) = QuerySuggestion;

  factory Suggestion.fromJson(Map<String, dynamic> json) => _$SuggestionFromJson(json);
}

class SuggestionConverter implements JsonConverter<Suggestion, Map<String, dynamic>> {
  const SuggestionConverter();

  @override
  Suggestion fromJson(Map<String, dynamic> json) {
    if (json.containsKey(placePredictionKey)) {
      return PlaceSuggestion.fromJson(json[placePredictionKey]);
    } else if (json.containsKey(queryPredictionKey)) {
      return QuerySuggestion.fromJson(json[queryPredictionKey]);
    } else {
      throw Exception('Could not determine the constructor for mapping prediction from JSON');
    }
  }

  @override
  Map<String, dynamic> toJson(Suggestion data) =>
      data.map(place: (p) => {placePredictionKey: p.toJson()}, query: (q) => {queryPredictionKey: q.toJson()});
}
flutter dart riverpod google-places-autocomplete flutter-change-notifier-provider
1个回答
0
投票

问题在于

suggestionsBuilder
回调不会对触发
build
方法的更改做出反应(换句话说,当由于正在监视的
build
有一个值改变,
queryServiceProvider
回调不会再次被调用)。

suggestionsBuilder

依赖其控制器来更新建议值,因此您必须

强制
更新它,即通过在SearchAnchor回调中调用控制器的适当设置器。
例如:

ref.listen

ref.listen(todoProvider(id), (_, suggestions) {
  _searchController.text = ... // store the value from `sugesstions` to the controller text
});
© www.soinside.com 2019 - 2024. All rights reserved.