使用flutter_bloc加载更多数据时发出另一个状态

watbbzwu  于 2023-01-21  发布在  Flutter
关注(0)|答案(1)|浏览(142)

如何实现flutter_bloc加载更多数据,无需每次重载:我有这个:
后_块. dart:

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:scroool/post_events.dart';
import 'package:scroool/post_repo.dart';
import 'package:scroool/post_states.dart';

class PostsBloc extends Bloc<PostEvents, PostsStates> {
  PostRepo repo;

  int page = 1;

  ScrollController controller = ScrollController();

  PostsBloc(this.repo) : super(PostInitState()){
    on<FetchPosts>((event, emit) async{
        emit(PostLoadingState());
        final posts = await repo.fetchPosts(page);
        emit(PostLoadedState(posts: posts));
    });

    on<LoadMore>((event, emit) async{
      if (controller.position.pixels ==
          controller.position.maxScrollExtent) {
       emit(LoadMoreState());
        page++;
        final posts = await repo.fetchPosts(page);
        emit(PostLoadedState(posts: posts));

      //  isLoadingMore = false;
      } else {
        print("not called");
      }
    });
  }

}

在家也是。

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:scroool/post_bloc.dart';
import 'package:scroool/post_events.dart';
import 'package:scroool/post_states.dart';

class Scroool extends StatelessWidget {
  List posts = [];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: BlocConsumer<PostsBloc, PostsStates>(
        listener: (context, state){},
        builder: (context, state) {
          if(state is PostLoadingState) {
            return const Center(child: CircularProgressIndicator(),);
          } else if(state is PostLoadedState) {
            posts = posts + state.posts;
            return ListView.builder(
              controller: context.read<PostsBloc>().controller
                ..addListener(() => context.read<PostsBloc>().add(LoadMore())),
              itemCount: state is LoadMoreState
                  ? posts.length + 1 : posts.length ,
              itemBuilder: (context, index) {
                if(index < posts.length) {
                  final post = posts[index];
                  return Card(
                      child: ListTile(
                        leading: CircleAvatar(child: Text("${index + 1}"),),
                        title: Text(post['author'].toString()),
                        subtitle: Text(post['title']['rendered']),
                      )
                  );
                } else {
                  return Center(child: CircularProgressIndicator(),);
                }
              },
            );

          } else {
            return Container();
          }

        },
      )
    );
  }
}

它的工作没有任何问题,但每次我需要加载更多的只是重新发射的状态和显示数据从头开始,我只需要继续更多的数据,而不是重新加载和添加所有数据

rjee0c15

rjee0c151#

更改BLoC状态,使父状态具有属性posts。对于不使用该属性的状态,可以将其设置为空列表。

abstract class PostState {
  final List<Post> posts;

  PostState(this.posts);
}

class PostLoadingState extends PostState {
  LoadMoreState() : super ([]);
}

class LoadMoreState extends PostState {
  LoadMoreState({required List<Post> posts}) : super (posts);
}

class PostLoadedState extends PostState {
  PostLoadedState({required List<Post> posts}) : super (posts);
}

然后相应地更改您的BLoC:

on<LoadMore>((event, emit) async{
  if (controller.position.pixels ==
      controller.position.maxScrollExtent) {
    emit(LoadMoreState(posts: state.posts));
    page++;
    final posts = await repo.fetchPosts(page);
    emit(PostLoadedState(posts: [...state.posts, ...posts]));
  } else {
    print("not called");
  }
});

在小部件中,删除变量posts,并使用bloc状态中的posts。由于父状态具有属性posts,因此可以为每个状态访问posts,包括LoadMoreState。因此,更改if条件,为除PostLoadingState之外的所有状态返回ListView

class Scroool extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: BlocConsumer<PostsBloc, PostsStates>(
          listener: (context, state){},
          builder: (context, state) {
            if(state is PostLoadingState) {
              return const Center(child: CircularProgressIndicator(),);
            } else {
              final posts = state.posts;

              return ListView.builder(
                controller: context.read<PostsBloc>().controller
                  ..addListener(() => context.read<PostsBloc>().add(LoadMore())),
                itemCount: state is LoadMoreState
                    ? posts.length + 1 : posts.length ,
                itemBuilder: (context, index) {
                  if(index < posts.length) {
                    final post = posts[index];
                    return Card(
                        child: ListTile(
                          leading: CircleAvatar(child: Text("${index + 1}"),),
                          title: Text(post['author'].toString()),
                          subtitle: Text(post['title']['rendered']),
                        )
                    );
                  } else {
                    return Center(child: CircularProgressIndicator(),);
                  }
                },
              );
            }
          },
        )
    );
  }
}

相关问题