#javascript #flutter
Вопрос:
Я разрабатываю прототип приложения с помощью flutter . Один из экранов позволяет пользователям обновлять количество, и он также вызывает конечную точку.
Я не хочу повторно отображать содержимое экрана после того, как пользователь увеличит количество, Вот мой код, любая помощь будет признательна
import 'package:flutter/material.dart'; import 'dart:async'; import 'package:http/http.dart' as http; import 'dart:convert'; class ProductDetailScreen extends StatelessWidget{ @override Widget build(BuildContext context) { return MaterialApp( title: "Product #1", home:Scaffold( appBar: AppBar( title: const Text('Product #1', style: TextStyle(color: Colors.deepOrange)), backgroundColor: Colors.white, iconTheme: IconThemeData(color: Colors.deepOrange), actions: lt;Widgetgt;[ IconButton(onPressed: (){ ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('This is a snackbar'))); },icon: const Icon(Icons.shopping_cart),color: Colors.deepOrange,) ], leading: BackButton(color: Colors.deepOrange, onPressed: () =gt; Navigator.of(context).pop()) ), body: SafeArea(child: Center( child: ProductsDetailsScreen() ), ), ), ); } } class ProductsDetailsScreen extends StatefulWidget{ const ProductsDetailsScreen({Key? key}) : super(key: key); @override _ProductsDetailScreenState createState() =gt; _ProductsDetailScreenState(); } class _ProductsDetailScreenState extends Statelt;ProductsDetailsScreengt; { int qty = 0; void _increment(){ setState((){ qty = qty 1; }); } Futurelt;Listgt; fetchProduct() async{ final response = await http.get(Uri.parse('https://www.thecocktaildb.com/api/json/v1/1/random.php')); final product = json.decode(response.body); List prod = product['drinks']; Listlt;Prodgt; prods = []; print(response); for(var p in prod){ Prod product = Prod(idDrink: p["idDrink"],strDrink: p['strDrink'],strDrinkThumb: p['strDrinkThumb'] ); prods.add(product); } return prods; } @override Widget build(BuildContext context) { return Container( child:FutureBuilder( future : fetchProduct(), builder: (BuildContext context, AsyncSnapshot snapshot){ if(snapshot.data == null) { return Container( child:Text("Loading...") ); }else { return Column( children: Listlt;Widgetgt;.generate(snapshot.data.length,(int index) { return ( Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children :lt;Widgetgt;[ Image.network(snapshot.data[index].strDrinkThumb, fit: BoxFit.contain, ), Text(snapshot.data[index].strDrink.toUpperCase(), style: TextStyle(color: Colors.black,fontFamily: "Verdana", fontSize: 20, ), ), Text('49.00', style: TextStyle(color: Colors.deepOrange,fontFamily: "Verdana", fontSize: 20, ), ), Row( //crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children :lt;Widgetgt;[ Expanded( flex:2, child: ElevatedButton( onPressed: (){}, child: Text('-'), style: ElevatedButton.styleFrom(primary:Colors.deepOrange, ),) ), Expanded( flex:6, child: Container(alignment: Alignment.center, child:Text('$qty')), ), Expanded( flex:2, child:ChangeQuantity(_increment) // child: ElevatedButton( // onPressed:() =gt;{changeQty()}, // child: Text(' '), // style: ElevatedButton.styleFrom(primary:Colors.deepOrange, // ),) ), ] ), Column( crossAxisAlignment: CrossAxisAlignment.stretch, children:lt;Widgetgt; [ ElevatedButton.icon( icon: Icon(Icons.shopping_basket_rounded), onPressed: (){}, label: Text('Add to trolley'), style: ElevatedButton.styleFrom(primary:Colors.deepOrange, ), )] ) ], ) ); } ) ); }} ) ); } } class ChangeQuantity extends StatefulWidget { final VoidCallback increment; ChangeQuantity(this.increment); @override _ChangeQtyScreenState createState() =gt; _ChangeQtyScreenState(); } class _ChangeQtyScreenState extends Statelt;ChangeQuantitygt; { @override Widget build(BuildContext context) { return ElevatedButton( onPressed: widget.increment, child: Text(' '), style: ElevatedButton.styleFrom(primary:Colors.deepOrange)); } }
Этот код работает, но не так, как я хочу. Я обнаружил, что при увеличении количества страница снова отображается, и выполняется вызов uri, который отображает
Ответ №1:
В _ProductsDetailScreenState, чтобы не выполнять повторную визуализацию, переместите List.generate в параметр statefulwidget. Передайте снимок.данные в этот параметр состояния. Таким образом, каждый раз, когда вы нажимаете на кнопку увеличения, этот параметр statefulwidget будет перезагружаться, а не метод сборки _ProductsDetailScreenState, избегающий попадания в API.
class _ProductsDetailScreenState extends Statelt;ProductsDetailsScreengt; { Listlt;intgt; qty = []; …….. @override Widget build(BuildContext context) { return Container( child: FutureBuilder( future: fetchProduct(), builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.data == null) { return Container(child: Text("Loading...")); } else { qty = List.filled((snapshot.data as List).length, 0); return CustomWidget(snapshot.data, qty); } })); } } class CustomWidget extends StatefulWidget { final Listlt;Drinksgt; drinks; final Listlt;intgt; qty; CustomWidget(this.drinks, this.qty); @override Statelt;StatefulWidgetgt; createState() =gt; _CustomWidgetState(); } class _CustomWidgetState extends Statelt;CustomWidgetgt; { _increment(int index) { setState(() { widget.qty[index] ; print(widget.qty[index]); }); } @override Widget build(BuildContext context) { return Column( children: Listlt;Widgetgt;.generate(widget.drinks.length, (int index) { return Expanded( child: (Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: lt;Widgetgt;[ Image.network( widget.drinks[index].strDrinkThumb, fit: BoxFit.contain, width: 40, height: 40, ), Text( widget.drinks[index].strDrink.toUpperCase(), style: TextStyle( color: Colors.black, fontFamily: "Verdana", fontSize: 20, ), ), Text( '49.00', style: TextStyle( color: Colors.deepOrange, fontFamily: "Verdana", fontSize: 20, ), ), Row( //crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: lt;Widgetgt;[ Expanded( flex: 2, child: ElevatedButton( onPressed: () {}, child: Text('-'), style: ElevatedButton.styleFrom( primary: Colors.deepOrange, ), )), Expanded( flex: 6, child: Container( alignment: Alignment.center, child: Text('${widget.qty[index]}')), ), Expanded(flex: 2, child: ChangeQuantity(_increment, index)), ]), Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: lt;Widgetgt;[ ElevatedButton.icon( icon: Icon(Icons.shopping_basket_rounded), onPressed: () {}, label: Text('Add to trolley'), style: ElevatedButton.styleFrom( primary: Colors.deepOrange, ), ) ]) ], )), ); })); } } class ChangeQuantity extends StatefulWidget { final ValueChangedlt;intgt; increment; final int index; ChangeQuantity(this.increment, this.index); @override _ChangeQtyScreenState createState() =gt; _ChangeQtyScreenState(); } class _ChangeQtyScreenState extends Statelt;ChangeQuantitygt; { @override Widget build(BuildContext context) { return ElevatedButton( onPressed: () { widget.increment(widget.index); }, child: Text(' '), style: ElevatedButton.styleFrom(primary: Colors.deepOrange)); } }