Потяните, чтобы обновить, не перестанет обновляться во флаттере

У меня есть вопрос

здесь я получаю данные из API и создал вторую страницу, которую могу опубликовать из своего приложения в API.

когда я публикую что-то и возвращаюсь на главную страницу, где все сообщения из моего API освещены, мне нужно обновить... когда я обновляю его, новое сообщение будет добавлено, но обновляющий круг не будет хватит обновляться..

Я понятия не имею, что делать ..

В одном месте я прочитал, что это из-за заданного состояния, которое создает бесконечный цикл.. но в моем случае мне нужно заданное состояние для обновления пользовательского интерфейса.. пожалуйста, скажите мне, что делать. пожалуйста, помогите мне, спасибо.

это мой код:

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyPage(),
    );
  }
}

class MyPage extends StatefulWidget {
  const MyPage({super.key});

  @override
  State<MyPage> createState() => _MyPageState();
}

class _MyPageState extends State<MyPage> {
  final RefreshController _myrefreshcontroller = RefreshController();
  late List<Post>? listpost;
  @override
  void initState() {
    fetchAllPosts().then((value) => listpost = value);
    super.initState();
  }

  void _onRefresh() async {
    await fetchAllPosts().then((value) {
      setState(() {
        listpost = value;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('welcome welcome'),
      ),
      body: Center(
        child: FutureBuilder(
          future: fetchAllPosts(),
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return SmartRefresher(
                controller: _myrefreshcontroller,
                onRefresh: _onRefresh,
                child: ListView.builder(
                  itemCount: listpost!.length,
                  itemBuilder: (context, index) {
                    return Card(
                      child: ListTile(
                        contentPadding: const EdgeInsets.all(20),
                        title: Padding(
                            padding: const EdgeInsets.all(20),
                            child: Text(listpost![index].id.toString())),
                        subtitle: Padding(
                            padding: const EdgeInsets.all(20),
                            child: Text(listpost![index].content.toString())),
                      ),
                    );
                  },
                ),
              );
            } else if (snapshot.hasError) {
              return Text("${snapshot.error}");
            }
            return const CircularProgressIndicator();
          },
        ),
      ),

Какие ошибки вы получаете, если таковые имеются? Как выглядит ваша функция fetchAllPosts?

returnVoid 28.06.2024 20:30
1
1
56
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Возможно, это из-за SmartRefresher, я не знаю, почему вы не использовали обычный виджет RefreshIndicator. У меня это отлично работает, даже с setState()

Future<void> delay() async {
   await Future.delayed(Duration(seconds: 4)).then((value) {
     setState(() {});
   });
}

...
child: RefreshIndicator(
  onRefresh: delay,
  child: child,
),
...

Проблема в том, что вы выполняете fetchAllPosts(). Вам следует передать эту функцию в качестве параметра будущему методу FutureBuilder следующим образом:

future: fetchAllPosts,

но что на самом деле принято и неправильно, так это следующее:

future: fetchAllPosts()

Ответ принят как подходящий

Пакет, который вы используете для обновления, рекомендует добавлять _refreshController.refreshCompleted() при успешном обновлении, которого нет в вашем коде. После небольшой обработки ошибок это должно выглядеть так:

void _onRefresh() async {
    fetchAllPosts().then((value) {
      setState(() {
        listPost = value;
      });
      _refreshController.refreshCompleted();
    }).catchError((error) {
      _refreshController.refreshFailed();
    });
  }

И да, хотя setState вызвал бы бесконечный цикл, если бы вы использовали значение RefreshIndicator Flutter по умолчанию, в случаях, когда вам нужно запустить перестройку в вашем FutureBuilder без сброса будущего, вы можете обойти это, сначала сделав будущее запомненным.

Таким образом, запоминание вашего будущего изменит поведение вашего FutureBuilder, чтобы оно восстанавливалось только тогда, когда само будущее меняется, а не при каждом setState звонке.

Для этого, исходя из вашего кода, код перед вашим методом _onRefresh теперь будет выглядеть так:

  final RefreshController _refreshController = RefreshController();
  late Future<List<Post>> futurePosts;
  late List<Post>? listPost;

  @override
  void initState() {
    super.initState();
    futurePosts = fetchAllPosts();
  }

и в своем FutureBuilder вы обновите будущее, чтобы использовать запомненные данные, которые тогда будут выглядеть так:

FutureBuilder<List<Post>>(
   future: futurePosts,
    …

Другие вопросы по теме