You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Bloc页面切换时实例重复加载问题求助

问题解决方案

问题根源分析

  1. 自定义StreamController不符合flutter_bloc的规范,且依赖监听状态判断是否加载数据,页面销毁后监听取消,再次进入会重新触发加载。
  2. 通过构造函数传递Bloc实例的方式不规范,容易出现实例管理混乱。
  3. ImageList的initState每次都会调用loadImages,没有判断数据是否已加载。

1. 重构Bloc实现(遵循flutter_bloc规范)

移除自定义StreamController,改用Bloc自带的事件-状态流管理数据:

DataList dataList = DataList();

// 定义事件
abstract class ImageListEvent {}
class LoadImagesEvent extends ImageListEvent {}

// 定义状态
abstract class ImageListState {}
class ImageListInitial extends ImageListState {}
class ImageListLoading extends ImageListState {}
class ImageListLoaded extends ImageListState {
  final List<String> images;
  ImageListLoaded(this.images);
}
class ImageListError extends ImageListState {
  final String error;
  ImageListError(this.error);
}

class ImageListBloc extends Bloc<ImageListEvent, ImageListState> {
  List<String>? _cachedImages;
  ImageListBloc() : super(ImageListInitial()) {
    on<LoadImagesEvent>(_onLoadImages);
  }

  Future<void> _onLoadImages(LoadImagesEvent event, Emitter<ImageListState> emit) async {
    // 缓存数据存在则直接返回,避免重复加载
    if (_cachedImages != null) {
      emit(ImageListLoaded(_cachedImages!));
      return;
    }
    emit(ImageListLoading());
    try {
      var dList = await dataList.gitListData();
      _cachedImages = dList;
      emit(ImageListLoaded(dList));
    } catch (e) {
      emit(ImageListError(e.toString()));
    }
  }
}

2. 在全局/父级提供Bloc实例

确保整个导航树共享同一个Bloc实例,避免传递实例的麻烦:

void main() {
  runApp(
    BlocProvider(
      create: (context) => ImageListBloc(),
      child: const MyApp(),
    ),
  );
}

3. 修改HomePage代码(无需传递Bloc)

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: const Text('Home')),
        body: Center(
          child: ElevatedButton(
            onPressed: () {
              Navigator.push(
                  context,
                  MaterialPageRoute(
                      builder: (context) => const ImageList()));
            },
            child: const Text('Go to Image List'),
          ),
        ));
  }
}

4. 修改ImageList代码(通过BlocProvider获取实例)

用BlocBuilder监听Bloc状态,无需手动管理Stream:

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

  @override
  State<ImageList> createState() => _ImageListState();
}

class _ImageListState extends State<ImageList> {
  @override
  void initState() {
    super.initState();
    // 仅首次进入时触发加载
    BlocProvider.of<ImageListBloc>(context).add(LoadImagesEvent());
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Image List')),
      body: BlocBuilder<ImageListBloc, ImageListState>(
        builder: (context, state) {
          if (state is ImageListLoading) {
            return const CircularProgressIndicator();
          }
          if (state is ImageListError) {
            return Text('Error: ${state.error}');
          }
          if (state is ImageListLoaded) {
            return ListView.builder(
              itemCount: state.images.length,
              itemBuilder: (context, index) {
                return Text(state.images[index]);
              },
            );
          }
          return const Text('No data available');
        },
      ),
    );
  }
}

内容的提问来源于stack exchange,提问作者Sanwar Jayswal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 15:09:56