How to implement pagination in Flutter Search Delegate? - flutter

I am trying to implement pagination in my app when a user searches for something.
I have been able to fetch and display my data(limited to like 12 results) but I have been unable to get more results due to Search Delegate not being a stateful class.
Is there a way I can use setState effectively to load more data by adding to my already fetched listView?
Code
import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:official_coolkicks/models/shoe.dart';
import 'package:official_coolkicks/providers/search-provider.dart';
import 'package:official_coolkicks/providers/shoe-provider.dart';
import 'package:official_coolkicks/themes/adjust_settings_icons.dart';
import 'package:official_coolkicks/views/widgets/category/shoeCard.dart';
import 'package:official_coolkicks/views/widgets/filtering/filter_chip.dart';
import 'package:provider/provider.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
class CategorySearch extends SearchDelegate<Shoe> {
#override
ThemeData appBarTheme(BuildContext context) {
assert(context != null);
final ThemeData theme = Theme.of(context);
assert(theme != null);
return theme;
}
ScrollController _sc = new ScrollController();
List<Shoe> shoes;
int page = 1;
bool isLoading = false;
#override
String get searchFieldLabel => 'Search in Men\'s Shoes';
var random = new Random();
Future _saveList() async {
SharedPreferences.getInstance().then((prefs) {
prefs.setStringList("searchHistory", searchHistory);
});
}
Widget content;
#override
List<Widget> buildActions(BuildContext context) {
return [
IconButton(
icon: Icon(Icons.clear),
onPressed: () {
query = "";
},
)
];
}
#override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: AnimatedIcon(
icon: AnimatedIcons.menu_arrow,
progress: transitionAnimation,
),
onPressed: () {
close(context, null);
});
}
#override
Widget buildResults(BuildContext context) {
final double height = MediaQuery.of(context).size.height;
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
void loadMore() {
setState(() {
page++;
isLoading = true;
print('ISLOADING IS EQUALS TO $isLoading');
});
}
setState(() {
if (page > 1) {
page++;
print('PAGE IS NOW $page');
}
});
return FutureBuilder(
future: _search(page),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
print(snapshot.error);
return Center(
child: Text('Check your Internet connection and try again'),
);
} else if (snapshot.data.length == 0) {
return Center(
child: Text('No search results found'),
);
}
return Container(
height: height,
child: Stack(
children: [
Column(
children: <Widget>[
Expanded(
child: NotificationListener<ScrollNotification>(
child: GridView.count(
padding: EdgeInsets.all(15),
controller:
new ScrollController(keepScrollOffset: false),
shrinkWrap: true,
childAspectRatio:
MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.3),
scrollDirection: Axis.vertical,
crossAxisCount: 2,
crossAxisSpacing: 15,
mainAxisSpacing: 15,
children: List.generate(
snapshot.data.length,
(index) {
return ShoeCard(
index: random.nextInt(1000000),
shoe: snapshot.data[index]);
},
),
),
onNotification: (ScrollNotification scrollInfo) {
if (scrollInfo.metrics.pixels ==
scrollInfo.metrics.maxScrollExtent) {
// loadMore();
}
return false;
},
)),
],
),
Align(
alignment: FractionalOffset.bottomCenter,
child: Container(
height: isLoading ? 50 : 0,
child: Center(
child: CircularProgressIndicator(),
))),
Align(
alignment: FractionalOffset.bottomRight,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: FloatingActionButton(
child: Icon(AdjustSettings.adjust),
backgroundColor: Colors.deepPurple,
onPressed: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (context) => FilterChipDisplay()));
},
),
),
),
],
));
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
);
});
}
#override
Widget buildSuggestions(BuildContext context) {
// List<Product> shoeList = products;
return Container();
}
Future<List<Shoe>> _search(int page) async {
String baseurl = "https://coolke.herokuapp.com";
String formatter(String url) {
return baseurl + url;
}
String url = formatter('/coolke/getCategorySearch/Men/$query?$page');
final result = await http.get(url);
final nlist = json.decode(result.body);
final list = nlist['shoes'] as List;
return list.map((e) => Shoe.fromJson(e)).toList();
}
}

Related

How to Pause and Resume the qr_code_scanner using the NavigationBar

I have a NavigationBar with 3 Destinations and I want to pause or resume the qr_code_scanner depending on what destination is focused, to do this i use a if to evaluate the index and pause or resume the scanner, but i dont now how pass the controller between classes.
My NavigationBar
bottomNavigationBar: NavigationBar(
elevation: 2,
labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected,
selectedIndex: index,
onDestinationSelected: (index) {
setState(() => this.index = index);
if (index == 1) {
widget.controller!.resumeCamera();
} else {
widget.controller!.pauseCamera();
}
},
destinations: const [
NavigationDestination(
icon: Icon(Icons.store_outlined),
selectedIcon: Icon(Icons.store),
label: 'Tienda',
),
NavigationDestination(
icon: Icon(Icons.qr_code_scanner_outlined),
selectedIcon: Icon(Icons.qr_code_scanner),
label: 'Escaner',
),
NavigationDestination(
icon: Icon(Icons.shopping_cart_outlined),
selectedIcon: Icon(Icons.shopping_cart),
label: 'Carrito',
),
],
),
The Home class
class Home extends StatefulWidget {
final QRViewController? controller;
const Home({Key? key, this.controller}) : super(key: key);
#override
State<Home> createState() => _HomeState();
}
My QrScan Class
class QRScanner extends StatefulWidget {
const QRScanner({Key? key}) : super(key: key);
#override
State<StatefulWidget> createState() => QRScannerState();
}
class QRScannerState extends State<QRScanner> {
Barcode? result;
QRViewController? controller;
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
#override
void reassemble() {
super.reassemble();
if (Platform.isAndroid) {
controller!.pauseCamera();
}
controller!.resumeCamera();
}
#override
Widget build(BuildContext context) {
void home() {
Home(
controller: controller,
);
}
home();
return Scaffold(
body: Column(
children: <Widget>[
Expanded(child: buildQrView(context)),
Align(
alignment: Alignment.bottomCenter,
child: Container(
alignment: Alignment.center,
height: 100,
color: Colors.black,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
margin: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await controller?.toggleFlash();
setState(() {});
},
child: FutureBuilder(
future: controller?.getFlashStatus(),
builder: (context, snapshot) {
if (snapshot.data == true) {
return const Icon(Icons.flash_on);
} else {
return const Icon(Icons.flash_off);
}
// Text('Flash: ${snapshot.data}');
},
)),
),
const Padding(padding: EdgeInsets.fromLTRB(37, 0, 0, 0)),
if (result != null)
Text('ID:${result!.code}')
else
const Text('Escanee el QR del producto'),
],
),
),
)
],
),
);
}
Widget buildQrView(BuildContext context) {
// For this example we check how width or tall the device is and change the scanArea and overlay accordingly.
var scanArea = (MediaQuery.of(context).size.width < 400 ||
MediaQuery.of(context).size.height < 400)
? 150.0
: 300.0;
// To ensure the Scanner view is properly sizes after rotation
// we need to listen for Flutter SizeChanged notification and update controller
return QRView(
key: qrKey,
onQRViewCreated: onQRViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.white,
borderRadius: 10,
borderLength: 30,
borderWidth: 10,
cutOutSize: scanArea),
onPermissionSet: (ctrl, p) => onPermissionSet(context, ctrl, p),
);
}
void onQRViewCreated(QRViewController controller) {
setState(() {
this.controller = controller;
});
controller.scannedDataStream.listen((scanData) {
setState(() {
result = scanData;
});
controller.pauseCamera();
Stream<List<Products>> readProducts() => FirebaseFirestore.instance
.collection('products')
.where('id', isEqualTo: '${result!.code}')
.snapshots()
.map((snapshot) => snapshot.docs
.map((doc) => Products.fromJson(doc.data()))
.toList());
Future<bool> onWillPop() async {
return false;
}
showDialog(
barrierDismissible: false,
context: context,
builder: (BuildContext context) => WillPopScope(
onWillPop: () async => false,
child: WillPopScope(
onWillPop: onWillPop,
child: Dialog(
insetPadding: const EdgeInsets.all(8),
child: StreamBuilder<List<Products>>(
stream: readProducts(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text('Algo ha ocurrido! ${snapshot.error}');
} else if (snapshot.hasData) {
final products = snapshot.data!;
return Container(
margin: const EdgeInsets.all(8),
child: Column(
mainAxisSize: MainAxisSize.min,
children: products
.map((p) => BuildProducts(
products: p, controller: controller))
.toList()),
);
} else {
return const Center(child: CircularProgressIndicator());
}
}),
),
),
),
);
});
}
void onPermissionSet(BuildContext context, QRViewController ctrl, bool p) {
log('${DateTime.now().toIso8601String()}_onPermissionSet $p');
if (!p) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('no Permission')),
);
}
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
}

StramBuilder not working , with no errors. FLUTTER

hey guys I'm new to Flutter, and I'm turning to build a very simple chat app for learning purposes, I'm using StreamBulider for that, it shows me no errors, but it's not working
I tread to add Text Widget on its own without the streambuilder so I can make sure that the problem with the streambulder function not anything else and it's works fine
can anyone help find what went wrong?
here is my code
import 'package:flutter/material.dart';
import 'package:flash_chat/constants.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class ChatScreen extends StatefulWidget {
static String id = 'chat_screen';
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final _fireStore = FirebaseFirestore.instance;
final _auth = FirebaseAuth.instance;
late String messegeText;
late User loogedInUser;
#override
void initState() {
super.initState();
getCurrentUser();
}
//------------------------------------------------------------------------------
// GetCurrentUser Method...
void getCurrentUser() async {
try {
// ignore: await_only_futures
final user = await _auth.currentUser;
if (user != null) {
loogedInUser = user;
}
} catch (e) {
print(e);
}
}
//------------------------------------------------------------------------------
// Get Masseges Method...
void messegesStream() async {
await for (var snapshot in _fireStore.collection('messeges').snapshots()) {
for (var message in snapshot.docs) {
print(message.data());
}
}
}
//------------------------------------------------------------------------------
// Code Start...
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepPurpleAccent,
leading: null,
actions: <Widget>[
IconButton(
icon: const Icon(Icons.download),
onPressed: () {
messegesStream();
// _auth.signOut();
// Navigator.pop(context);
}),
],
title: const Text('⚡️Chat'),
),
body: Container(
constraints: const BoxConstraints.expand(),
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage("images/background.jpg"), fit: BoxFit.cover),
),
child: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
//------------------------------------------------------------
// StreamBuilder method...
StreamBuilder<QuerySnapshot>(
stream: _fireStore.collection('messages').snapshots(),
builder: (context, snapshot) {
List<Text> messageWidgets = [];
if (snapshot.hasData) {
final messages = snapshot.data!.docs;
for (var message in messages) {
final messageText = message.get('text');
final messageSender = message.get('sender');
final messageWidget =
Text('$messageSender said $messageText');
messageWidgets.add(messageWidget);
}
}
return Column(
children: messageWidgets,
);
},
),
//------------------------------------------------------------
Container(
decoration: kMessageContainerDecoration,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
onChanged: (value) {
messegeText = value;
},
decoration: kMessageTextFieldDecoration,
),
),
MaterialButton(
onPressed: () {
_fireStore.collection('messeges').add(
{
'text': messegeText,
'sender': loogedInUser.email,
},
);
},
child: const Text(
'Send',
style: kSendButtonTextStyle,
),
),
],
),
),
],
),
),
),
);
}
}
my android emulator screen,
Try this code:
StreamBuilder<QuerySnapshot>(
stream: _fireStore.collection('messages').snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> chatSnapshot) {
if (chatSnapshot.connectionState == ConnectionState.waiting) {
return Center(
child: Container(),
);
}
return ListView(
reverse: true,
controller: _controller,
physics: const BouncingScrollPhysics(),
children:
chatSnapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data =
document.data()! as Map<String, dynamic>;
return Text(data["text"]);
}).toList(),
);
},
),

my snapshot doesn't have the data in futurebuilder

pls, help if you can .i am trying to fetch some data from rest api .but on the getTreadingWallpapers() method it shows me full json data. but whenever I print snapshot.hasError on else condition.. it shows me false. it means the snapshot has not error..but why i am not getting the data in my future builder. no error showing , how can i solve this problem
class _FrontPageState extends State<FrontPage> {
Future<List<RecentPage>> recentPage;
RecentPage recentPagee;
bool isLoading = true;
List<RecentPage> wallpapers = new List();
Future<List<RecentPage>> getTrendingWallpapers() async {
// final url ="http://wallpaper.pkappstudio.info/api/api.php?action=get_recent";
String url = 'http://wallpaper.pkappstudio.info/api/api.php?action=get_recent';
final response =
await Http.get(url, headers: {"Accept": "application/json"});
if (response.statusCode == 200) {
final Map = jsonDecode(response.body);
print("${response.body}");
isLoading = false;
final recentPaget = recentPageFromJson(response.body).asMap();
recentPaget.entries.forEach((element) => wallpapers.add(element.value));
return wallpapers;
} else {
throw Exception('Failed to load post');
}
}
#override
void initState() {
// TODO: implement initState
recentPage = getTrendingWallpapers();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(title: brandName(),elevation: 0.0,),
body: FutureBuilder(
future: recentPage,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.none &&
snapshot.hasData == null) {
print('project snapshot data is: ${snapshot.data}');
return isLoading? Center(child: Container(child: Text("container"),)):Center(child: Container(child: Text("csdsdontainer"),));
}
if(snapshot.hasData){
return isLoading? Center(child: CircularProgressIndicator()):ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index){
return Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: GridView.count(
shrinkWrap: true,
crossAxisCount: 2,
physics: ClampingScrollPhysics(),
childAspectRatio: 0.6,
mainAxisSpacing: 6.0,
crossAxisSpacing: 6.0,
children: wallpapers.map((wallpapers){
return GridTile(child: GestureDetector(
onTap: (){
// Navigator.push(context, MaterialPageRoute(builder: (context)=>ImageView(
// imageUrl: wallpapers.src.potrait,
// )));
},
child: Container(
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child:Image.network(snapshot.data.imageUrl, fit: BoxFit.cover,),
),
),
));
}).toList(),
),
);
},
);
} else return Container(child: Text("${snapshot.hasError}"),);
},
)
);
}
}
You can copy paste run full code below
Step 1: You do not need isLoading , you can directly use check ConnectionState
Step 2: You do not need to declare List<RecentPage> wallpapers, snapshot.data already keep this
code snippet
builder: (context, AsyncSnapshot<List<RecentPage>> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('none');
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
case ConnectionState.active:
return Text('');
case ConnectionState.done:
if (snapshot.hasError) {
return Text(
'${snapshot.error}',
style: TextStyle(color: Colors.red),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: GridView.count(
shrinkWrap: true,
crossAxisCount: 2,
physics: ClampingScrollPhysics(),
childAspectRatio: 0.6,
mainAxisSpacing: 6.0,
crossAxisSpacing: 6.0,
children: snapshot.data.map((wallpapers) {
return GridTile(
child: GestureDetector(
onTap: () {
// Navigator.push(context, MaterialPageRoute(builder: (context)=>ImageView(
// imageUrl: wallpapers.src.potrait,
// )));
},
child: Container(
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Image.network(
wallpapers.imageUrl,
fit: BoxFit.cover,
working demo
full code
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
List<RecentPage> recentPageFromJson(String str) =>
List<RecentPage>.from(json.decode(str).map((x) => RecentPage.fromJson(x)));
String recentPageToJson(List<RecentPage> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class RecentPage {
RecentPage({
this.no,
this.imageId,
this.imageUpload,
this.imageUrl,
this.type,
this.viewCount,
this.downloadCount,
this.featured,
this.tags,
this.categoryId,
this.categoryName,
});
int no;
String imageId;
String imageUpload;
String imageUrl;
Type type;
String viewCount;
String downloadCount;
Featured featured;
String tags;
String categoryId;
String categoryName;
factory RecentPage.fromJson(Map<String, dynamic> json) => RecentPage(
no: json["no"],
imageId: json["image_id"],
imageUpload: json["image_upload"],
imageUrl: json["image_url"],
type: typeValues.map[json["type"]],
viewCount: json["view_count"],
downloadCount: json["download_count"],
featured: featuredValues.map[json["featured"]],
tags: json["tags"],
categoryId: json["category_id"],
categoryName: json["category_name"],
);
Map<String, dynamic> toJson() => {
"no": no,
"image_id": imageId,
"image_upload": imageUpload,
"image_url": imageUrl,
"type": typeValues.reverse[type],
"view_count": viewCount,
"download_count": downloadCount,
"featured": featuredValues.reverse[featured],
"tags": tags,
"category_id": categoryId,
"category_name": categoryName,
};
}
enum Featured { YES, NO }
final featuredValues = EnumValues({"no": Featured.NO, "yes": Featured.YES});
enum Type { UPLOAD }
final typeValues = EnumValues({"upload": Type.UPLOAD});
class EnumValues<T> {
Map<String, T> map;
Map<T, String> reverseMap;
EnumValues(this.map);
Map<T, String> get reverse {
if (reverseMap == null) {
reverseMap = map.map((k, v) => new MapEntry(v, k));
}
return reverseMap;
}
}
class FrontPage extends StatefulWidget {
#override
_FrontPageState createState() => _FrontPageState();
}
class _FrontPageState extends State<FrontPage> {
Future<List<RecentPage>> recentPage;
RecentPage recentPagee;
bool isLoading = true;
List<RecentPage> wallpapers = new List();
Future<List<RecentPage>> getTrendingWallpapers() async {
// final url ="http://wallpaper.pkappstudio.info/api/api.php?action=get_recent";
String url =
'http://wallpaper.pkappstudio.info/api/api.php?action=get_recent';
final response =
await http.get(url, headers: {"Accept": "application/json"});
if (response.statusCode == 200) {
final Map = jsonDecode(response.body);
print("${response.body}");
isLoading = false;
final recentPaget = recentPageFromJson(response.body).asMap();
recentPaget.entries.forEach((element) => wallpapers.add(element.value));
return wallpapers;
} else {
throw Exception('Failed to load post');
}
}
#override
void initState() {
// TODO: implement initState
recentPage = getTrendingWallpapers();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text("brandName()"),
elevation: 0.0,
),
body: FutureBuilder(
future: recentPage,
builder: (context, AsyncSnapshot<List<RecentPage>> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('none');
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
case ConnectionState.active:
return Text('');
case ConnectionState.done:
if (snapshot.hasError) {
return Text(
'${snapshot.error}',
style: TextStyle(color: Colors.red),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: GridView.count(
shrinkWrap: true,
crossAxisCount: 2,
physics: ClampingScrollPhysics(),
childAspectRatio: 0.6,
mainAxisSpacing: 6.0,
crossAxisSpacing: 6.0,
children: snapshot.data.map((wallpapers) {
return GridTile(
child: GestureDetector(
onTap: () {
// Navigator.push(context, MaterialPageRoute(builder: (context)=>ImageView(
// imageUrl: wallpapers.src.potrait,
// )));
},
child: Container(
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Image.network(
wallpapers.imageUrl,
fit: BoxFit.cover,
),
),
),
));
}).toList(),
),
);
},
);
}
}
}));
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: FrontPage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
There is a good implementation of a FutureBuilder widget
Future<List<dynamic>> getTrendingWallpapers() async {
String url = 'http://wallpaper.pkappstudio.info/api/api.php?action=get_recent';
final response = await http.get(url, headers: {"Accept": "application/json"});
if (response.statusCode == 200) {
List<dynamic> wallpapers = List();
wallpapers.add(response.body);
return wallpapers;
} else {
throw Exception('Failed to load post');
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: getTrendingWallpapers(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting || snapshot.connectionState == ConnectionState.none) {
return Center(child: CircularProgressIndicator());
}
if (snapshot.hasError) {
return Center(
child: Text('Future error'),
);
}
if (snapshot.hasData) {
return Center(
child: Text('Do something with your snapshot.data : \n ${snapshot.data}'),
);
}
},
),
);
}

Am Trying To calculate total price of a List of items

am making a shopping cart app where I want to calculate the total price of the products present in the cart I made a function for it and tried executing in init state but it's not working
import 'package:flutter/material.dart';
import 'package:shop/Models/Database.dart';
class Cart extends StatefulWidget {
#override
_CartState createState() => _CartState();
}
class _CartState extends State<Cart> {
int sum = 0;
total() {
studlist.forEach((element) {
sum = sum + element.price;
});
}
#override
void initState() {
total();
super.initState();
}
final DbStudentManager dbmanager = new DbStudentManager();
Student cart;
List<Cart> cartList;
int updateIndex;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'Cart',
style: TextStyle(color: Colors.black),
),
),
body: FutureBuilder(
future: dbmanager.getStudentList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
studlist = snapshot.data;
}
return ListView.builder(
itemCount: studlist == null ? 0 : studlist.length,
itemBuilder: (BuildContext context, int index) {
Student ct = studlist[index];
return Card(
child: ListTile(
title: Text(ct.name),
subtitle: Text('${ct.price}'),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
dbmanager.deleteStudent(ct.id);
setState(() {
studlist.remove(index);
});
}),
),
);
});
}),
bottomNavigationBar: Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Text('$sum'),
SizedBox(
width: 10,
),
Text('Check Out'),
],
),
),
],
),
);
}
}
the error I get:
The method 'forEach' was called on null.
Receiver: null
Tried calling: forEach(Closure: (Student) => Null)
Try this:
import 'package:flutter/material.dart';
import 'package:shop/Models/Database.dart';
class Cart extends StatefulWidget {
#override
_CartState createState() => _CartState();
}
class _CartState extends State<Cart> {
int sum = 0;
#override
void initState() {
super.initState();
}
final DbStudentManager dbmanager = new DbStudentManager();
Student cart;
List<Cart> studList=[];
int updateIndex;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'Cart',
style: TextStyle(color: Colors.black),
),
),
body: FutureBuilder(
future: dbmanager.getStudentList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
studlist = snapshot.data;
studlist.forEach((element) {
setState((){
sum = sum + element.price;
});
});
}
return ListView.builder(
itemCount: studlist == null ? 0 : studlist.length,
itemBuilder: (BuildContext context, int index) {
Student ct = studlist[index];
return Card(
child: ListTile(
title: Text(ct.name),
subtitle: Text('${ct.price}'),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
dbmanager.deleteStudent(ct.id);
setState(() {
studlist.remove(index);
});
}),
),
);
});
}),
bottomNavigationBar: Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Text('$sum'),
SizedBox(
width: 10,
),
Text('Check Out'),
],
),
),
],
),
);
}
}
Try running total() function if the data when the data is loaded, not in init. As data is initially empty, running it inside init will cause this error.
if (snapshot.hasData) {
studlist = snapshot.data;
total();
}
Full Code:
import 'package:flutter/material.dart';
import 'package:shop/Models/Database.dart';
class Cart extends StatefulWidget {
#override
_CartState createState() => _CartState();
}
class _CartState extends State<Cart> {
int sum = 0;
total() {
studlist.forEach((element) {
sum = sum + element.price;
});
}
final DbStudentManager dbmanager = new DbStudentManager();
Student cart;
List<Cart> cartList;
int updateIndex;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'Cart',
style: TextStyle(color: Colors.black),
),
),
body: FutureBuilder(
future: dbmanager.getStudentList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
studlist = snapshot.data;
total(); //Run the total() function here
}
return ListView.builder(
itemCount: studlist == null ? 0 : studlist.length,
itemBuilder: (BuildContext context, int index) {
Student ct = studlist[index];
return Card(
child: ListTile(
title: Text(ct.name),
subtitle: Text('${ct.price}'),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
dbmanager.deleteStudent(ct.id);
setState(() {
studlist.remove(index);
});
}),
),
);
});
}),
bottomNavigationBar: Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Text('$sum'),
SizedBox(
width: 10,
),
Text('Check Out'),
],
),
),
],
),
);
}
}
try this
If I added Quantity increased totalQty but I have one issue if I removing Item in list
did not decrease. sorry my english not good
`total() {
studlist.forEach((element) {
if(element.qty!=null){
totalQty=totalQty+element.qty;
print(totalQty);
}
});
}
`

Flutter Bloc with audioplayers

Almost a day of figuring way how to do it and I need your help.
I've created an app that would have a state with an instance of audioplayers and using flutter_bloc.
Problems:
The state player plays but the Widget MusicPlayer doesn't rebuild the widget with the BlocBuilder
I'm trying also to get the currentPosition and duration of the music I'm playing and displaying it using LinearPercentIndicator from linear_percent_indicator package but can't seem to find a solution because rebuild doesn't work.
What am I missing?
Here's what I have so far:
Bloc
class AudioPlayerBloc extends Bloc<AudioPlayerEvents, MusicPlayerState> {
#override
MusicPlayerState get initialState => MusicPlayerState(
player: AudioPlayer(),
episode: Episode(),
);
#override
Stream<MusicPlayerState> mapEventToState(AudioPlayerEvents event) async* {
if (event is InitializePlayer) {
this.currentState.episode = event.episode;
this.dispatch(PlayPlayer());
yield this.currentState;
}
if (event is PlayPlayer) {
this.play(this.currentState.episode.source);
}
if (event is PlayRemote) {
this.currentState.player.stop();
this.currentState.player.play(event.remoteURL);
yield this.currentState;
}
if (event is ShowPlayer) {
yield this.currentState;
}
if (event is HidePlayer) {
yield this.currentState;
}
}
void play(String remoteURL) {
this.dispatch(PlayRemote(remoteURL));
}
void stop() async {
await this.currentState.player.stop();
}
void pause() async{
await this.currentState.player.pause();
}
void resume(){
this.currentState.player.resume();
}
#override
void dispose() {
super.dispose();
}
}
Event
abstract class AudioPlayerEvents {}
class InitializePlayer extends AudioPlayerEvents {
Episode episode;
InitializePlayer(this.episode);
}
class PlayRemote extends AudioPlayerEvents {
final String remoteURL;
PlayRemote(this.remoteURL);
}
class PlayPlayer extends AudioPlayerEvents {}
class ShowPlayer extends AudioPlayerEvents {}
class HidePlayer extends AudioPlayerEvents {}
State
import 'package:audioplayers/audioplayers.dart';
class MusicPlayerState {
AudioPlayer player;
Episode episode; // My Custom Class
MusicPlayerState({
this.player,
this.episode,
});
}
main.dart
#override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<AudioPlayerBloc>(
builder: (_) => AudioPlayerBloc(),
)
],
child: MaterialApp(
navigatorObservers: [],
initialRoute: HomeScreen.id,
routes: {
HomeScreen.id: (context) => HomeScreen(app: widget.app),
},
),
);
}
}
MusicPlayer.dart <-- my Player Widget
class MusicPlayer extends StatelessWidget {
#override
Widget build(BuildContext context) {
final AudioPlayerBloc audioPlayerBloc =
BlocProvider.of<AudioPlayerBloc>(context);
return BlocBuilder<AudioPlayerBloc, MusicPlayerState>(
bloc: audioPlayerBloc,
builder: (context, state) {
return Container(
height: 200.0,
color: Colors.cyan[200],
child: Padding(
padding: const EdgeInsets.only(top: 20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Column(
children: <Widget>[
Text("${state.episode.name}"),
Row(
children: <Widget>[
Expanded(
flex: 1,
child: FutureBuilder<int>(
future: audioPlayerBloc.currentState.player.getCurrentPosition(),
builder: (context, AsyncSnapshot<int> snapshot) {
double seconds = snapshot.data / 1000;
if (snapshot.hasData) {
return Text("${printDuration(Duration(seconds: seconds.toInt()), abbreviated: true)}");
} else {
return Text('Calculating..');
}
},
),
),
Expanded(
flex: 3,
child: LinearPercentIndicator(
lineHeight: 7.0,
// percent: this.currentPosition / this.fileDuration,
percent: 0.3,
backgroundColor: Colors.grey,
progressColor: Colors.blue,
),
),
Expanded(
flex: 1,
child: FutureBuilder<int>(
future: audioPlayerBloc.currentState.player.getDuration(),
builder: (context, AsyncSnapshot<int> snapshot) {
double seconds = snapshot.data / 1000;
if (snapshot.hasData) {
return Text("${printDuration(Duration(seconds: seconds.toInt()), abbreviated: true)}");
} else {
return Text('Calculating..');
}
},
),
),
],
),
Text(state.player.state.toString()),
FlatButton(
onPressed: () {
print('close here');
Navigator.of(context).pop();
},
child: Icon(
Icons.close,
color: Colors.black.withOpacity(0.5),
),
),
Row(
children: <Widget>[
FlatButton(
onPressed: () {
audioPlayerBloc.pause();
},
child: Text('Pause Player'),
),
FlatButton(
onPressed: () {
audioPlayerBloc.resume();
},
child: Text('Resume Player'),
),
FlatButton(
onPressed: () {
audioPlayerBloc.stop();
},
child: Text('Stop Player'),
),
],
)
],
)
],
),
),
);
},
);
}
}
HomeScreen.dart <-- my first screen
#override
Widget build(BuildContext context) {
final AudioPlayerBloc audioPlayerBloc = BlocProvider.of<AudioPlayerBloc>(context);
return MultiBlocProvider(
providers: [
BlocProvider<AudioPlayerBloc>(
builder: (_) => AudioPlayerBloc(),
)
],
child: Scaffold(
appBar: AppBar(
title: Text('Global Audio Player'),
),
body: Container(
child: BlocBuilder<AudioPlayerBloc, MusicPlayerState>(
builder: (context, state) {
return Column(
children: <Widget>[
Flexible(
child: getListView(context)
),
displayPlayer(state.player), // Here I'm trying to display the player when the AudioPlayerState is PLAYING
],
);
},
),
),
),
);
}
Global function
Widget displayPlayer(AudioPlayer player){
return MusicPlayer();
if(player.state == AudioPlayerState.PLAYING) {
return MusicPlayer();
}
return Container();
}
EpisodesScreen.dart <-- ListView of the Episodes
class _EpisodesScreenState extends State<EpisodesScreen> {
#override
void initState() {
super.initState();
print(widget.series);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.series.name)),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
flex: 0,
child: Image.network(widget.series.image.original),
),
Expanded(
child: getListView(context),
),
Expanded(
child: BlocBuilder<AudioPlayerBloc, MusicPlayerState>(
builder: (context, state) {
return displayPlayer(state.player);
},
),
)
],
));
}
Widget getListView(BuildContext context) {
List<Episode> episodesList = widget.series.episodes;
final AudioPlayerBloc audioPlayerBloc =
BlocProvider.of<AudioPlayerBloc>(context);
var listView = ListView.separated(
itemCount: episodesList.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(episodesList[index].name),
trailing: BlocBuilder<AudioPlayerBloc, MusicPlayerState>(
builder: (context, state) {
return FlatButton(
onPressed: () {
audioPlayerBloc.dispatch(InitializePlayer(episodesList[index]));
},
child: Icon(
Icons.play_arrow,
color: Colors.black87,
),
);
},
),
);
},
separatorBuilder: (BuildContext context, int index) {
return Divider(
height: 1.0,
color: Colors.black12,
);
},
);
return listView;
}
}
I missed the yield * part of it and it is now working.
Stream<Duration> currentPosition() async* {
yield* this.currentState.audioPlayer.onAudioPositionChanged;
}
Stream<Duration> fileDuration() async* {
yield* this.currentState.audioPlayer.onDurationChanged;
}