如何从SearchAnchor手动重建suggestionBuilder?

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

我想使用SearchAnchor Widget,但不幸的是,我找不到触发重建的方法。我尝试了很多方法来实现类似于我的图片suggestionBuilder中的清单中所示的效果。但是,它不起作用,因为只有当我输入新文本并且触发搜索控制器时,小部件才会重建。

我尝试使用有状态小部件并更改状态,但它不起作用。我还尝试了 ValueListenableBuilder 并尝试手动编辑 SearchController,这绝对不是有效的解决方案,也不起作用。我什至尝试了 Riverpod Provider,如提供的最小代码片段所示。

这让我发疯。感谢您的任何帮助! :D

使用 Riverpod 进行重现的最小示例(我使用的是 Flutter 3.16.3):

import 'dart:async';
import 'dart:developer';

import 'package:flutter/material.dart';

import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

part 'init_jobs_screen.g.dart';

class InitJobsScreen extends ConsumerWidget {
  const InitJobsScreen({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    //This value i want to display
    int seconds = ref.watch(secondsCounterProvider);

    final SecondsCounter notifier = ref.watch(secondsCounterProvider.notifier);
    if (seconds == 0) {
      callFunctionEverySecond(notifier);
    }
    return Scaffold(
        appBar: AppBar(
          title: const Text('Whats going on here?!'),
        ),
        body: Column(
          children: [
            Text('Here it works as expected $seconds'),

            //Here the provider doesnt work -> It drives me quazy
            SearchAnchor.bar(
                suggestionsBuilder: (context, controller) =>
                    [Text(ref.watch(secondsCounterProvider).toString())]),
          ],
        ));
  }
}

//Provider i want to watch
@riverpod
class SecondsCounter extends _$SecondsCounter {
  @override
  int build() => 0;

  void incrementSeconds() => state++;
}

//increment seconds
void callFunctionEverySecond(SecondsCounter notifier) {
  // Call the function every second
  Timer.periodic(const Duration(seconds: 1), (timer) {
    log('increment Secondscounter');
    notifier.incrementSeconds();
  });
}

我尝试了有状态小部件并更改了状态,但这不起作用,我尝试了 ValueListenableBuilder,我尝试手动编辑 SearchController (这确实不是有效的解决方案,尽管不起作用),我尝试了 Riverpod Provider,就像提供的最小代码片段

rebuild
1个回答
0
投票

如果您转到源文件 search_anchor.dart,在第 765 行左右,找到

didChangeDependencies()
函数,您将看到 suggestBuilder 是如何触发的:

@override
  void didChangeDependencies() {
    super.didChangeDependencies();
    final Size updatedScreenSize = MediaQuery.of(context).size;

    if (_screenSize != updatedScreenSize) {
      _screenSize = updatedScreenSize;
      if (widget.showFullScreenView) {
        _viewRect = Offset.zero & _screenSize!;
      }
    }

    if (searchValue != _controller.text) {
      _timer?.cancel();
      _timer = Timer(Duration.zero, () async {
        searchValue = _controller.text;
        result = await widget.suggestionsBuilder(context, _controller);
        _timer?.cancel();
        _timer = null;
      });
    }
  }

注意线条:

if (searchValue != _controller.text){
     ...
     result = await widget.suggestionsBuilder(context, _controller);
     ...
}

所以改变文本确实是触发 suggestBuilder 的唯一条件。因此,在 Flutter 团队添加诸如 buildWhen 参数之类的内容之前,最好的选择是完全绕过它或重置文本。

每当我需要重建时我都会这样做。不是最漂亮的解决方案,并且会导致刷新,但却是解决问题的最快答案。

SearchController searchController = SearchController();
...
SearchAnchor(
    searchController: searchController,
    ...
);
...
final query = searchController.text;
searchController.text = '';
searchController.text = query;
© www.soinside.com 2019 - 2024. All rights reserved.