Добавление объекта в List Flutter
Продукт добавляется в лист, но не сохраняет продукт. При хот рестарте или переключении страниц лист становится пустой.
class ProductUi extends StatelessWidget {
ProductTest productTest;
ProductUi(this.productTest);
@override
Widget build(BuildContext context) {
final productBloc = BlocProvider.of<ProductBloc>(context);
return Scaffold(
body: Container(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(productTest.name),
RaisedButton(
onPressed: () {
productBloc.add(AddToCart(productTest: productTest));
},
child: Text('add to cart'),
),
],
),
)),
);
}
}
Функции
class CartService {
List<ProductTest> cartProduct = [];
Future addProduct(ProductTest productTest) async {
return cartProduct.add(productTest);
}
}
блок
class ProductBloc extends Bloc<ProductEvent, ProductState> {
CartService cartService = CartService();
ProductBloc({@required this.cartService});
@override
ProductState get initialState => ProductInitial();
@override
Stream<ProductState> mapEventToState(ProductEvent event) async* {
if (event is AddToCart) {
await cartService.addProduct(event.productTest);
}
}
}
Ивент
class AddToCart extends ProductEvent {
ProductTest productTest;
AddToCart({this.productTest});
@override
List<Object> get props => [];
}
Home screen
class HomeScreenTest extends StatefulWidget {
@override
_HomeScreenTestState createState() => _HomeScreenTestState();
}
class _HomeScreenTestState extends State<HomeScreenTest> {
CartService cartService = CartService();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Padding(
padding: const EdgeInsets.only(top: 4),
child: SizedBox(
height: kToolbarHeight,
child: Image.asset('assets/dafna_logo.png'),
),
),
backgroundColor: Colors.blueGrey,
elevation: 20,
),
body: CategoryTest(),
);
}
}
class CategoryTest extends StatefulWidget {
@override
_CategoryTestState createState() => _CategoryTestState();
}
class _CategoryTestState extends State<CategoryTest> {
CartService cartService = CartService();
@override
Widget build(BuildContext context) {
BlocProvider.of<ProductBloc>(context)..add(LoadCategoriesEvent());
return Scaffold(
backgroundColor: Colors.blueGrey[400],
body: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.fromLTRB(20, 15, 20, 15),
child: Column(
children: <Widget>[
Text('Категории'),
BlocBuilder<ProductBloc, ProductState>(
builder: (context, state) {
if (state is ProductLoaded) {
return categoryColumn(
state.categoriesTest, state.productTest);
} else {
return Container();
}
},
)
],
),
),
),
);
}
Widget categoryColumn(
List<CategoriesTest> categoriesTest, List<ProductTest> productTest) {
return Column(
children: categoriesTest.map((category) {
return Card(
color: Colors.blueGrey[300],
elevation: 10.0,
margin: EdgeInsets.fromLTRB(10, 10, 10, 10),
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BlocProvider(
create: (context) =>
ProductBloc(cartService: cartService),
child: ProductList(
categoriesTest: category,
))));
},
child: Container(
padding: EdgeInsets.all(20),
child: Column(
children: <Widget>[
Text(
category.categoryname,
),
],
),
),
),
);
}).toList(),
);
}
class ProductList extends StatefulWidget {
CategoriesTest categoriesTest;
ProductList({@required this.categoriesTest});
@override
_ProductListState createState() => _ProductListState();
}
class _ProductListState extends State<ProductList> {
CartService cartService = CartService();
@override
Widget build(BuildContext context) {
BlocProvider.of<ProductBloc>(context)..add(LoadProductListEvent());
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blueGrey,
),
backgroundColor: Colors.blueGrey[100],
body: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.fromLTRB(20, 30, 20, 15),
child: Column(
children: <Widget>[
BlocBuilder<ProductBloc, ProductState>(
builder: (context, state) {
if (state is TableListLoaded) {
return tableListColumn(
state.productTest, widget.categoriesTest);
} else {
return Container();
}
},
)
],
),
),
),
);
}
Widget tableListColumn(
List<ProductTest> productTest, CategoriesTest categoriesTest) {
return Column(
children: productTest
.where((product) => product.category == categoriesTest.categoryname)
.map((product) {
return Card(
elevation: 10.0,
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BlocProvider(
create: (context) =>
ProductBloc(cartService: cartService),
child: ProductUi(product))));
},
child: Container(
padding: EdgeInsets.all(15),
child: Column(
children: <Widget>[
Image.network(product.image),
Text(product.name),
],
),
),
),
);
}).toList(),
);
}
}
Ответы (1 шт):
У вас есть класс CartService, вы создаете объект этого класса (CartService cartService = CartService();) в классе ProductUi. Данный объект существует только в данном классе. Когда данный класс уничтожается (например при хот рестарте или при переключении страницы назад) объекты в нем тоже уничтожаются.
Чтобы избежать этого, необходимо создать объект класса CartService выше по дереву виджетов и передавать его через конструктор:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final CartService cartService = CartService();
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: SecondRoute(cartService),
),
),
);
}
}
class CartService {
List<ProductTest> cartProduct = [];
void addProduct(ProductTest productTest) {
cartProduct.add(productTest);
}
}
class ProductTest {
final String name;
ProductTest(this.name);
}
class SecondRoute extends StatelessWidget {
final CartService cartService;
SecondRoute(this.cartService);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
ProductUi(ProductTest("name"), cartService)));
},
child: Text("Go Next"),
),
),
);
}
}
class ProductUi extends StatelessWidget {
final ProductTest productTest;
final CartService cartService;
ProductUi(this.productTest, this.cartService);
@override
Widget build(BuildContext context) {
final productList = cartService.cartProduct;
return Scaffold(
body: Container(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(productTest.name),
RaisedButton(
onPressed: () {
cartService.addProduct(productTest);
productList.forEach((v) => print(v.name));
print("----");
},
child: Text('add to list'),
),
RaisedButton(
child: Text('go back'),
onPressed: () {
Navigator.pop(context);
},
),
],
),
),
),
);
}
}
Либо сделать класс CartService Singleton (предоставляет глобальную точку доступа к экземпляру класса, неубиваемый объект) и использовать его в любом месте (обращаю внимание на то что просто так создовать Singleton не стоит, так как он занимает место в памяти, и чем больше в нем объектов, тем больще места он будет занимать):
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final CartService cartService = CartService();
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: SecondRoute(),
),
),
);
}
}
class CartService {
static final CartService _singleton = CartService._internal();
factory CartService() => _singleton;
CartService._internal();
List<ProductTest> cartProduct = [];
void addProduct(ProductTest productTest) {
cartProduct.add(productTest);
}
}
class ProductTest {
final String name;
ProductTest(this.name);
}
class SecondRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
ProductUi(ProductTest("name"))));
},
child: Text("Go Next"),
),
),
);
}
}
class ProductUi extends StatelessWidget {
final ProductTest productTest;
ProductUi(this.productTest);
final CartService cartService = CartService();
@override
Widget build(BuildContext context) {
final productList = cartService.cartProduct;
return Scaffold(
body: Container(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(productTest.name),
RaisedButton(
onPressed: () {
cartService.addProduct(productTest);
productList.forEach((v) => print(v.name));
print("----");
},
child: Text('add to list'),
),
RaisedButton(
child: Text('go back'),
onPressed: () {
Navigator.pop(context);
},
),
],
),
),
),
);
}
}
Для того чтобы сохронить данный при перезапуске приложения, необходимо ипользовать базу данных, сохронять и загружать данные с неё.