如果在 bloc 构建器外部调用,flutter bloc 的状态不会更新
The state of flutter bloc is not updating if called outside the bloc builder
我在我的主文件中初始化了所有必要的块。即使在此之后,如果从 bloc 构建器外部调用,bloc 的状态也不会更新。
我正在尝试使用 bloc 模式实现延迟加载。
假设的操作是当列表视图到达末尾时滚动侦听器调用一个 bloc 函数,该函数将获取下一个项目并将最新项目与之前的项目一起传递给 ProductsLoadedState();
但是,即使在从 bloc 发出状态后,ProductsLoadedState 也不会被触发。
非常感谢您的帮助。
谢谢。
我的集团代码是:
void _onLoadProducts(
LoadProductsPage event, Emitter<ProductsPageState> emit) async {
print("getting products");
page == 1
? emit(const ProductsPageLoadingState(isFirstFetch: true))
: emit(ProductsPageLoadingState(
oldProducts: this.products, isFirstFetch: false));
final List<ProductModel> products =
await productsRepository.handleGetSearchedProducts(
event.title,
event.category,
event.brand,
event.condition,
event.productCode,
page);
page++;
print("page number $page");
this.products.addAll(products);
print(this.products.length);
emit(ProductsPageLoadedState(searchedProducts: this.products));
}
Main.dart 文件:
final AppRouter _appRouter = AppRouter();
MyApp({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<ProductsPageBloc>(
create: (context) => ProductsPageBloc(),
),
],
child: MultiRepositoryProvider(
providers: [
RepositoryProvider(create: (context) => ProductsRepository()),
RepositoryProvider(create: (context) => AuthRepository()),
RepositoryProvider(create: (context) => BrandRepository()),
],
child: MaterialApp(
title: 'title',
theme: ThemeData(
primarySwatch: Colors.blue,
fontFamily: 'T MS',
scaffoldBackgroundColor: const Color(0xffF6F6F9)),
onGenerateRoute: _appRouter.onGenerateRoute,
// home : AddressesPage(),
home: BlocProvider(
create: (context) => NetworkBloc(),
child: BlocBuilder<NetworkBloc, NetworkState>(
builder: (context, state) {
return UserMain();
},
),
),
),
));
}
}
Products.dart 文件:
class ProductsPage extends StatefulWidget {
final String title;
final String category;
final String brand;
final String condition;
final int pageNumber;
final String productCode;
const ProductsPage(
{Key key,
this.title,
this.category,
this.brand,
this.condition,
this.pageNumber,
this.productCode})
: super(key: key);
@override
_ProductsPageState createState() => _ProductsPageState();
}
class _ProductsPageState extends State<ProductsPage> {
String appBarTitle;
List<ProductModel> products = [];
bool isLoading = false;
final scrollController = ScrollController();
void setupScrollController(context) {
scrollController.addListener(() {
if (scrollController.position.atEdge) {
if (scrollController.position.pixels != 0) {
BlocProvider.of<ProductsPageBloc>(context).add(LoadProductsPage(
title: widget.title,
category: widget.category,
brand: widget.brand,
condition: widget.condition,
pageNumber: widget.pageNumber,
productCode: widget.productCode));
}
}
});
}
@override
void initState() {
setupScrollController(context);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(50),
child: CustomAppBar(
isSearchPage: true,
title: "tilte",
enableSearchBar: true,
),
),RepositoryProvider.of<ProductsRepository>(context)
body: BlocProvider(
create: (context) => ProductsPageBloc()
..add(
LoadProductsPage(
title: widget.title,
category: widget.category,
brand: widget.brand,
condition: widget.condition,
pageNumber: widget.pageNumber,
productCode: widget.productCode),
),
child: Scaffold(body: Center(
child: BlocBuilder<ProductsPageBloc, ProductsPageState>(
builder: (context, state) {
if (state is ProductsPageLoadingState) {
if (state.isFirstFetch) {
print("is first fetch");
return const LoadingSpinnerWidget();
} else {
print("is not first fetch${state.oldProducts}");
products = state.oldProducts;
}
} else if (state is ProductsPageLoadedState) {
isLoading = false;
print("is loaded ${state.searchedProducts} $isLoading");
products = state.searchedProducts;
print("state${state.searchedProducts.length}");
print("products${products.length}");
}
if (products.isNotEmpty) {
return ListView.builder(
controller: scrollController,
itemCount: products.length + (isLoading ? 1 : 0),
itemBuilder: (context, index) {
if (index < products.length) {
return ProductHorizontal(product: products[index]);
} else {
Timer(const Duration(milliseconds: 30), () {
scrollController.jumpTo(
scrollController.position.maxScrollExtent);
});
return const LoadingSpinnerWidget();
}
});
} else {
return const ShowCustomPage(
icon: CupertinoIcons.bag,
title:
"Sorry, we couldn't find any similar products. Please try searching for other products",
);
}
},
),
)),
),
);
}
}
您似乎在使用 ProductsPageBloc
的不同实例。通过预先初始化来确保使用相同的对象。例如:
final productsBloc = ProductsPageBloc();
...
void setupScrollController(context) {
scrollController.addListener(() {
if (scrollController.position.atEdge) {
if (scrollController.position.pixels != 0) {
productsBloc.add(LoadProductsPage(
title: widget.title,
category: widget.category,
brand: widget.brand,
condition: widget.condition,
pageNumber: widget.pageNumber,
productCode: widget.productCode));
}
}
});
}
...
body: BlocProvider(
create: (context) => productsBloc..add
...
希望对您有所帮助。
我在我的主文件中初始化了所有必要的块。即使在此之后,如果从 bloc 构建器外部调用,bloc 的状态也不会更新。
我正在尝试使用 bloc 模式实现延迟加载。
假设的操作是当列表视图到达末尾时滚动侦听器调用一个 bloc 函数,该函数将获取下一个项目并将最新项目与之前的项目一起传递给 ProductsLoadedState();
但是,即使在从 bloc 发出状态后,ProductsLoadedState 也不会被触发。
非常感谢您的帮助。 谢谢。
我的集团代码是:
void _onLoadProducts(
LoadProductsPage event, Emitter<ProductsPageState> emit) async {
print("getting products");
page == 1
? emit(const ProductsPageLoadingState(isFirstFetch: true))
: emit(ProductsPageLoadingState(
oldProducts: this.products, isFirstFetch: false));
final List<ProductModel> products =
await productsRepository.handleGetSearchedProducts(
event.title,
event.category,
event.brand,
event.condition,
event.productCode,
page);
page++;
print("page number $page");
this.products.addAll(products);
print(this.products.length);
emit(ProductsPageLoadedState(searchedProducts: this.products));
}
Main.dart 文件:
final AppRouter _appRouter = AppRouter();
MyApp({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<ProductsPageBloc>(
create: (context) => ProductsPageBloc(),
),
],
child: MultiRepositoryProvider(
providers: [
RepositoryProvider(create: (context) => ProductsRepository()),
RepositoryProvider(create: (context) => AuthRepository()),
RepositoryProvider(create: (context) => BrandRepository()),
],
child: MaterialApp(
title: 'title',
theme: ThemeData(
primarySwatch: Colors.blue,
fontFamily: 'T MS',
scaffoldBackgroundColor: const Color(0xffF6F6F9)),
onGenerateRoute: _appRouter.onGenerateRoute,
// home : AddressesPage(),
home: BlocProvider(
create: (context) => NetworkBloc(),
child: BlocBuilder<NetworkBloc, NetworkState>(
builder: (context, state) {
return UserMain();
},
),
),
),
));
}
}
Products.dart 文件:
class ProductsPage extends StatefulWidget {
final String title;
final String category;
final String brand;
final String condition;
final int pageNumber;
final String productCode;
const ProductsPage(
{Key key,
this.title,
this.category,
this.brand,
this.condition,
this.pageNumber,
this.productCode})
: super(key: key);
@override
_ProductsPageState createState() => _ProductsPageState();
}
class _ProductsPageState extends State<ProductsPage> {
String appBarTitle;
List<ProductModel> products = [];
bool isLoading = false;
final scrollController = ScrollController();
void setupScrollController(context) {
scrollController.addListener(() {
if (scrollController.position.atEdge) {
if (scrollController.position.pixels != 0) {
BlocProvider.of<ProductsPageBloc>(context).add(LoadProductsPage(
title: widget.title,
category: widget.category,
brand: widget.brand,
condition: widget.condition,
pageNumber: widget.pageNumber,
productCode: widget.productCode));
}
}
});
}
@override
void initState() {
setupScrollController(context);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(50),
child: CustomAppBar(
isSearchPage: true,
title: "tilte",
enableSearchBar: true,
),
),RepositoryProvider.of<ProductsRepository>(context)
body: BlocProvider(
create: (context) => ProductsPageBloc()
..add(
LoadProductsPage(
title: widget.title,
category: widget.category,
brand: widget.brand,
condition: widget.condition,
pageNumber: widget.pageNumber,
productCode: widget.productCode),
),
child: Scaffold(body: Center(
child: BlocBuilder<ProductsPageBloc, ProductsPageState>(
builder: (context, state) {
if (state is ProductsPageLoadingState) {
if (state.isFirstFetch) {
print("is first fetch");
return const LoadingSpinnerWidget();
} else {
print("is not first fetch${state.oldProducts}");
products = state.oldProducts;
}
} else if (state is ProductsPageLoadedState) {
isLoading = false;
print("is loaded ${state.searchedProducts} $isLoading");
products = state.searchedProducts;
print("state${state.searchedProducts.length}");
print("products${products.length}");
}
if (products.isNotEmpty) {
return ListView.builder(
controller: scrollController,
itemCount: products.length + (isLoading ? 1 : 0),
itemBuilder: (context, index) {
if (index < products.length) {
return ProductHorizontal(product: products[index]);
} else {
Timer(const Duration(milliseconds: 30), () {
scrollController.jumpTo(
scrollController.position.maxScrollExtent);
});
return const LoadingSpinnerWidget();
}
});
} else {
return const ShowCustomPage(
icon: CupertinoIcons.bag,
title:
"Sorry, we couldn't find any similar products. Please try searching for other products",
);
}
},
),
)),
),
);
}
}
您似乎在使用 ProductsPageBloc
的不同实例。通过预先初始化来确保使用相同的对象。例如:
final productsBloc = ProductsPageBloc();
...
void setupScrollController(context) {
scrollController.addListener(() {
if (scrollController.position.atEdge) {
if (scrollController.position.pixels != 0) {
productsBloc.add(LoadProductsPage(
title: widget.title,
category: widget.category,
brand: widget.brand,
condition: widget.condition,
pageNumber: widget.pageNumber,
productCode: widget.productCode));
}
}
});
}
...
body: BlocProvider(
create: (context) => productsBloc..add
...
希望对您有所帮助。