git链接:[项目代码][1][1]:https://github.com/SanwarJW/multi_bloc_provider
描述:
我在 Flutter 应用程序中面临状态管理和导航问题。我有两个页面(HomePage 和 ImageListPage),我在其中使用了一个块。我将块实例从 HomePage 传递到 ImageListPage。但是,每次我导航到 ImageListPage 时,块实例似乎都会重新加载,从而导致意外行为。
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
final imageListBloc = BlocProvider.of<ImageListBloc>(context);
return Scaffold(
appBar: AppBar(title: const Text('Home')),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ImageList(
imageListBloc: imageListBloc,
)));
},
child: const Text('Go to Image List'),
),
));
}
}
我有一个 Flutter 应用程序,有两个页面(HomePage 和 ImageListPage),使用 bloc 实例。我将块实例从 HomePage 传递到 ImageListPage。但是,每次我导航到 ImageListPage 时,块实例都会重新加载,从而导致意外行为。
class ImageList extends StatefulWidget {
final ImageListBloc imageListBloc;
const ImageList({super.key, required this.imageListBloc});
@override
State<ImageList> createState() => _ImageListState();
}
class _ImageListState extends State<ImageList> {
@override
void initState() {
super.initState();
widget.imageListBloc.loadImages();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Image List')),
body: Center(
child: StreamBuilder<List<String>>(
stream: widget.imageListBloc.imageListStream,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
}
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
}
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return Text(snapshot.data![index]);
},
);
} else {
// Handle the case when data is not available
return const Text('No data available');
}
},
),
),
);
}
}
这段Flutter Bloc代码定义了一个ImageListBloc,负责管理图像列表数据。它使用初始状态进行初始化并提供图像列表流。 loadImages 方法从 DataList 获取数据并将其发送到流
DataList dataList = DataList();
class ImageListBloc extends Bloc<ImageListEvent, ImageListState> {
ImageListBloc() : super(ImageListInitial()) {}
final _imageListController = StreamController<List<String>>.broadcast();
Stream<List<String>> get imageListStream => _imageListController.stream;
loadImages() async {
if (!_imageListController.hasListener) {
var dList = await dataList.gitListData();
_imageListController.sink.add(dList);
}
}
}
我尝试过的:
通过构造函数传递 bloc 实例。调查导航路线是否存在任何潜在问题。检查块实例是否在导航中正确保留。预期结果:
我希望在 HomePage 和 ImageListPage 之间导航时无需重新加载即可维护 bloc 实例,从而确保一致的行为和状态管理。
任何有关如何解决此问题的见解或建议将不胜感激。谢谢!
我不明白将
ImageListBloc
实例传递到 ImageList
小部件的目的。
我看到你已经在 main() 中添加了它
BlocProvider<ImageListBloc>(create: (context) => ImageListBloc())
,然后只需调用 context.read<ImageListBloc>(); to get the BLoc instance within the widget tree
。
并且在您的小部件中根本没有使用 Bloc,您对 Bloc 的使用就像包含 StreamController 的随机类。
每次导航到
ImageList
时,它都会重新加载,因为在 loadImages()
方法运行之前,在 initState()
方法中调用 build
函数。结果,StreamController
没有监听器,没有任何监听器,数据将被获取。
当您向后导航时,
ImageList
小部件将被释放,并且其侦听器将从流中删除。
如何修复
我的建议是正确使用 BLoc,向
ImageListState
添加更多状态
part of 'image_list_bloc.dart';
@immutable
sealed class ImageListState {}
final class ImageListInitial extends ImageListState {}
final class ImageListLoading extends ImageListState {}
final class ImageListLoaded extends ImageListState {
final List<String> listData;
ImageListLoaded ({required this.listData});
}
final class ImageListError extends ImageListState {}
ImageListBloc
(我在这里使用肘节作为简单的例子)
class ImageListBloc extends Cubit<ImageListState> {
ImageListBloc() : super(ImageListInitial()) {}
loadImages() async {
emit(ImageListLoading());
var dList = await dataList.gitListData();
emit(ImageListLoaded(listData: dList));
}
}
main()
BlocProvider<ImageListBloc>(create: (context) => ImageListBloc()..loadImages())
ImageList
class ImageList extends StatefulWidget {
const ImageList({super.key});
@override
State<ImageList> createState() => _ImageListState();
}
class _ImageListState extends State<ImageList> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Image List')),
body: BlocBuilder<ImageListBloc, ImageListState>(
buildWhen: (old, current) {
return current is ImageListLoading || current is ImageListLoaded || current is ImageListError;
},
builder: (context, state) {
if(state is ImageListLoading) {
return const CircularProgressIndicator();
}
if(state is ImageListError) {
return Text('Error: ${snapshot.error}');
}
if(state is ImageListLoaded) {
return ListView.builder(
itemCount: (state).listData.length,
itemBuilder: (context, index) {
return Text((state).listData[index]);
},
);
}
return const Text('No data available');
},
),
);
}
}
最后修正导航调用
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ImageList())
);