[英]How to use Streambuilder in flutter
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
void main() async {
//Run this first
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Smart Bin',
home: new HomePageWidget(),
);
}
}
class HomePageWidget extends StatefulWidget {
const HomePageWidget({Key key}) : super(key: key);
@override
_HomePageWidgetState createState() => _HomePageWidgetState();
}
class _HomePageWidgetState extends State<HomePageWidget> {
final scaffoldKey = GlobalKey<ScaffoldState>();
final currentBinRecord = FirebaseFirestore.instance.collection("current_bin");
@override
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
appBar: AppBar(
title: Text(
'SmartBin',
),
),
body: SafeArea(
child: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: StreamBuilder<List<CurrentBinRecord>>(
stream: queryCurrentBinRecord(
queryBuilder: (currentBinRecord) =>
currentBinRecord.orderBy('level', descending: true),
),
builder: (context, snapshot) {
// Customize what your widget looks like when it's loading.
if (!snapshot.hasData) {
return Center(
child: SizedBox(
width: 50,
height: 50,
child: CircularProgressIndicator(),
),
);
}
List<CurrentBinRecord> listViewCurrentBinRecordList =
snapshot.data;
return ListView.builder(
padding: EdgeInsets.zero,
scrollDirection: Axis.vertical,
itemCount: listViewCurrentBinRecordList.length,
itemBuilder: (context, listViewIndex) {
final listViewCurrentBinRecord =
listViewCurrentBinRecordList[listViewIndex];
return Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
listViewCurrentBinRecord.area,
),
Text(
listViewCurrentBinRecord.level.toString(),
),
],
);
},
);
},
),
),
],
),
),
),
);
}
}
First error is on:第一个错误是:
child: StreamBuilder<List<CurrentBinRecord>>
The name 'CurrentBinRecord' isn't a type so it can't be used as a type argument.
名称“CurrentBinRecord”不是类型,因此不能用作类型参数。 Try correcting the name to an existing type, or defining a type named 'CurrentBinRecord'.
尝试将名称更正为现有类型,或定义名为“CurrentBinRecord”的类型。
Second error is on:第二个错误是:
stream: queryCurrentBinRecord
The method 'queryCurrentBinRecord' isn't defined for the type '_HomePageWidgetState'.
未为类型“_HomePageWidgetState”定义方法“queryCurrentBinRecord”。 Try correcting the name to the name of an existing method, or defining a method named 'queryCurrentBinRecord'.
尝试将名称更正为现有方法的名称,或定义名为“queryCurrentBinRecord”的方法。
Third error is on:第三个错误是:
List<CurrentBinRecord> listViewCurrentBinRecordList =
snapshot.data;
The name 'CurrentBinRecord' isn't a type so it can't be used as a type argument.
名称“CurrentBinRecord”不是类型,因此不能用作类型参数。 Try correcting the name to an existing type, or defining a type named 'CurrentBinRecord'.
尝试将名称更正为现有类型,或定义名为“CurrentBinRecord”的类型。
These is the syntax try -这些是语法尝试 -
return StreamBuilder(
stream: theStreamSource, // Eg a firebase query
builder: (context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, int index) {
return Text(snapshot.data.documents[index]['title']);
}
);
},
);
Hope it helps.希望能帮助到你。
I think the best way to use StreamBuilder is to create separate controller class that can handle all your business logic and update UI.我认为使用 StreamBuilder 的最佳方式是创建单独的控制器类来处理您的所有业务逻辑和更新 UI。
// your widget class
class UIClass extends StatefulWidget {
const UIClass({Key key}) : super(key: key);
@override
_UIClassState createState() => _UIClassState();
}
class _UIClassState extends State<UIClass> {
UIClassController<List<CurrentBinRecord>> _uiController;
@override
void initState() {
_uiController = UIClassController(StreamController<List<CurrentBinRecord>>());
super.initState();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Text("Hello Everyone"),
StreamBuilder<List<CurrentBinRecord>>(
stream: _uiController.uiStream,
builder: (context, snapshot) {
if(snapshot.hasError){
return ErrorWidget();
}
else if(snapshot.connectionState == ConnectionState.waiting){
return WaitingWidget();
}
else if(snapshot.hasData){
return ListView.builder(
padding: EdgeInsets.zero,
scrollDirection: Axis.vertical,
itemCount: snapshot.data.length,
itemBuilder: (context, listViewIndex) {
final listViewCurrentBinRecord =
snapshot.data[listViewIndex];
return Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
listViewCurrentBinRecord.area,
),
Text(
listViewCurrentBinRecord.level.toString(),
),
],
);
},
);
}
else{
return SizedBox();
}
}
),
],
);
}
@override
void dispose() {
super.dispose();
_uiController.dispose();
}
}
// controller class to handle all business logic
// you can also split it into multiple sub controllers
class UIClassController<T> {
final StreamController<T> _controller;
// If you are using this on multiple widgets then use asBroadcastStream()
Stream<T> get uiStream => _controller.stream;
UIClassController(this._controller);
void updateMyUI([dynamic params]){
T t;
// your logic //
//------------//
_controller.sink.add(t);
}
void dispose(){
_controller.close();
}
}
Code I'm Using for StreamBuilder我用于 StreamBuilder 的代码
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import '../door/widgets/Navbar.dart';
import '../door/widgets/sidenav.dart';
import 'package:get/get.dart';
FirebaseAuth auth = FirebaseAuth.instance;
class CartPage extends StatefulWidget {
@override
_CartPageState createState() => _CartPageState();
}
class _CartPageState extends State<CartPage> {
final FirebaseFirestore fb = FirebaseFirestore.instance;
int up = 1;
bool loading = false;
final ScrollController _scrollController = ScrollController();
@override
void initState() {
super.initState();
getCartData();
}
void addMore(qty, documentID) {
int new_qty = qty + 1;
Get.snackbar('Qty! ', new_qty.toString());
String collection_name = "cart_${auth.currentUser?.email}";
FirebaseFirestore.instance
.collection(collection_name)
.doc(documentID)
.update({
'qty': new_qty,
'updated_at': Timestamp.now(),
}) // <-- Your data
.then((_) => print('Added'))
.catchError((error) => Get.snackbar('Failed!', 'Error: $error'));
}
void minusMore(qty, documentID) {
if (qty > 1) {
int new_qty = qty - 1;
String collection_name = "cart_${auth.currentUser?.email}";
FirebaseFirestore.instance
.collection(collection_name)
.doc(documentID)
.update({
'qty': new_qty,
'updated_at': Timestamp.now(),
}) // <-- Your data
.then((_) => print('Subtracted'))
.catchError((error) => Get.snackbar('Failed!', 'Error: $error'));
}
}
Stream<QuerySnapshot> getCartData() {
String collection_name = "cart_${auth.currentUser?.email}";
return FirebaseFirestore.instance
.collection(collection_name)
.orderBy("created_at", descending: false)
.snapshots();
}
final ButtonStyle style = ElevatedButton.styleFrom(
minimumSize: Size(50, 30),
backgroundColor: Color(0xFFFFB61A),
elevation: 6,
textStyle: const TextStyle(fontSize: 11),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(20),
)));
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: Navbar.navbar(),
drawer: Sidenav.sidenav(),
body: Container(
padding: EdgeInsets.all(10.0),
child: StreamBuilder<QuerySnapshot>(
stream: getCartData(),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
default:
if (snapshot.hasError) {
return buildText('Something Went Wrong Try later');
} else {
if (!snapshot.hasData) {
return Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
leading: ConstrainedBox(
constraints: const BoxConstraints(
minWidth: 100,
minHeight: 190,
maxWidth: 200,
maxHeight: 200,
),
child: Icon(Icons.shopping_cart, size: 45),
),
title: Text('No Food!'),
subtitle: const Text('Your cart is empty!'),
),
],
),
);
} else {
return ListView.builder(
physics: const BouncingScrollPhysics(),
shrinkWrap: true,
itemCount: snapshot.data?.docs.length,
itemBuilder: (BuildContext context, int index) {
return SizedBox(
height: 90.0,
child: Card(
elevation: 10,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
const SizedBox(
width: 20,
),
_buildImg('assets/logo.png', '60', '60'),
const SizedBox(
width: 14,
),
SizedBox(
width:
MediaQuery.of(context).size.width *
0.33,
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
const SizedBox(
height: 20,
),
Text(
snapshot.data?.docs[index]
["name"],
maxLines: 2,
style: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 14)),
const SizedBox(
height: 5,
),
Text(
"₹${snapshot.data?.docs[index]["price"]}",
style: const TextStyle(
fontWeight: FontWeight.w400,
fontSize: 12)),
],
),
),
const SizedBox(
width: 10,
),
Container(
margin: const EdgeInsets.only(
top: 20.0, bottom: 10.0),
decoration: BoxDecoration(
color: const Color(0xFFFFB61A),
// color: Color(0xFF0A2031),
borderRadius:
BorderRadius.circular(17)),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
crossAxisAlignment:
CrossAxisAlignment.end,
children: <Widget>[
SizedBox(
height: 40,
child: IconButton(
onPressed: () {
minusMore(
snapshot.data
?.docs[index]
["qty"],
snapshot
.data
?.docs[index]
.reference
.id);
},
color: Colors.white,
icon:
const Icon(Icons.remove)),
),
const SizedBox(
width: 5,
),
Container(
margin: const EdgeInsets.only(
bottom: 10.0),
child: Text(
"${snapshot.data?.docs[index]["qty"]}",
style: const TextStyle(
fontWeight:
FontWeight.w400,
color: Colors.white,
fontSize: 16)),
),
const SizedBox(
width: 5,
),
SizedBox(
height: 40,
child: IconButton(
color: Colors.white,
onPressed: () {
addMore(
snapshot.data
?.docs[index]
["qty"],
snapshot
.data
?.docs[index]
.reference
.id);
},
icon: const Icon(Icons.add)),
),
],
),
),
const SizedBox(
width: 10,
),
],
),
),
);
});
}
}
}
},
),
),
);
}
Widget buildText(String text) => Center(
child: Text(
text,
style: TextStyle(fontSize: 24, color: Colors.black),
),
);
_buildImg(img, hei, wid) {
return Container(
alignment: Alignment.center, // use aligment
child: Image.asset(
img,
height: double.parse(hei),
width: double.parse(wid),
fit: BoxFit.cover,
),
);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.