繁体   English   中英

当使用 flutter_bloc 加载更多数据时发出另一个 state

[英]emit another state when load more data with flutter_bloc

如何使用 flutter_bloc 加载更多数据而无需每次都重新加载:我有这个:

post_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");
      }
    });
  }


}

在家里。dart:

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();
          }

        },
      )
    );
  }
}

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

更改您的 BLoC state,这样父级 state 将拥有财产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 的 state 的posts 。由于您的父 state 具有属性posts ,您可以访问每个 state 的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(),);
                  }
                },
              );
            }
          },
        )
    );
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM