如何解决在单独的窗口小部件更新中更新状态
我试图弄清楚按下按钮时如何更新小部件的状态。
以下是一些屏幕截图,以说明我要完成的工作:
热重新加载应用程序时,更新生效,但是当我按下对话框上的更新按钮时,状态不会更新。
我知道有很多技术可以使它起作用,但我无法通过将函数传递给构造函数来使其更新。
我也不太想知道如何使用provider.of(context)而不传递一些值。这两个地方(mainDebt小部件和allDebts小部件)都没有使用任何值。
主页代码非常简单。一个无状态小部件,其中包含我需要显示的不同小部件:
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),),body: SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[
SizedBox(
height: 30,HpHeader(),SizedBox(height: 30),QuoteBox(),MainDebtDebt(),AdCard(),AllDebtsCard(),SizedBox(height: 10),RaisedButton(
child: Text('Enter Debt'),onpressed: () => Navigator.pushNamed(context,'/enterDebt1')),//etc........
mainDebtDebt是我需要更新状态的小部件。它是从SharedPreferences中读取数据,该数据是在我按下对话框上的更新按钮时设置的:
import 'dart:async';
//import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:debt_zero_2/classes/icon_class.dart';
import 'package:Flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class MainDebtDebt extends StatefulWidget {
@override
_MainDebtDebtState createState() => _MainDebtDebtState();
}
class _MainDebtDebtState extends State<MainDebtDebt> {
bool thenum = true;
static DebtModel debtIcons = DebtModel();
bool getGoalType = true;
double balance = 0.0;
String name = '';
String type = '';
int numOfDebts = 0;
double safetyBalance = 0.0;
double mainsnowballopeningBalance = 0.0;
Future<void> getGoalTypeFlag() async {
final SharedPreferences preferences = await SharedPreferences.getInstance();
final sortBy = preferences.getInt('sortBySNowOrAva');
setState(() {
if (sortBy == 1){
balance = preferences.getDouble('mainDebtFieldsnowball');
type = preferences.getString('mainDebtFieldsnowballType');
name = preferences.getString('mainDebtFieldsnowballName');}
if (sortBy == 2){
balance = preferences.getDouble('mainAvalancheBalance');
type = preferences.getString('mainAvalancheBalanceType');
name = preferences.getString('mainAvalancheBalanceName');
}
mainsnowballopeningBalance = preferences.getDouble('openingBalance');
safetyBalance = preferences.getDouble('safetyBalance');
getGoalType = preferences.getBool('mainGoalIsDebts');
numOfDebts = preferences.getInt('numberOfDebts');
});
}
@override
void initState() {
super.initState();
getGoalTypeFlag();
}
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,decoration: Boxdecoration(border: Border.all()),child: Column(
children: <Widget>[
Text(getGoalType
? 'I\'m Knocking Out This Payment:'
: 'I\'m Building My Safety Fund'),SizedBox(
height: 15,Row(
mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[
Text(
getGoalType
? debtIcons.getDebtIcon(type)
: '?',style: TextStyle(fontSize: 30),SizedBox(
width: 20,Text(getGoalType ? name : 'Safety Fund'),],children: <Widget>[
Text(getGoalType ? 'Remaining Balance:' : 'Saved:'),SizedBox(
width: 15,Text(getGoalType
? '\$' + balance.toStringAsFixed(0)
: safetyBalance.toStringAsFixed(0))
],Column(
children: <Widget>[
Text('Current Progress:'),SizedBox(
height: 10,Container(
decoration: Boxdecoration(border: Border.all()),height: 22,width: 202,child: Column(
crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[
Flexible(
child: FractionallySizedBox(
widthFactor: .75,//fix this
// 1 - mainsnowballBalance / mainsnowballopeningBalance,child: Container(
color: Colors.green,)
],SizedBox(
height: 15,RaisedButton(
child: Text(getGoalType ? 'MAKE A PAYMENT' : 'MAKE A DEPOSIT'),onpressed: () {
Navigator.of(context).pushNamed('/makePayment');
},SizedBox(
height: 30,RaisedButton(
child: Text('GET DATA'),onpressed: ()async {
SharedPreferences pref = await SharedPreferences.getInstance();
String thenum = pref.getString('debtId');
//pref.setBool('isInOb',null);
print(thenum);
},)
],);
}
}
排序对话框当前位于AllDebtsCard中。当前,它可以按最高利息或最低余额分别对列表进行排序:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:debt_zero_2/classes/min_debt_class.dart';
//import 'package:debt_zero_2/classes/icon_class.dart';
import 'package:debt_zero_2/widgets/provider_widget.dart';
import 'package:Flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:shared_preferences/shared_preferences.dart';
class AllDebtsCard extends StatefulWidget {
@override
_AllDebtsCardState createState() => _AllDebtsCardState();
}
class _AllDebtsCardState extends State<AllDebtsCard> {
int debtValue = 1;
int group;
void setValues() async {
SharedPreferences sharedPrefs = await SharedPreferences.getInstance();
final uid = await Provider.of(context).auth.getUidPref();
final db = Firestore.instance;
setState(() {
sharedPrefs.setInt('sortBySNowOrAva',debtValue);
SetMainDebt().setMainDebt();
});
db
.collection('userPreferences')
.document(uid)
.updateData({'sortBySNowOrAva': debtValue});
}
getValues() async {
SharedPreferences sharedPrefs = await SharedPreferences.getInstance();
int intValue = sharedPrefs.getInt('sortBySNowOrAva');
return intValue;
}
restore() async {
final SharedPreferences sharedPrefs = await SharedPreferences.getInstance();
setState(() {
group = (sharedPrefs.getInt('sortBySNowOrAva') ?? false);
});
}
final dbPath = Firestore.instance.collection('userDebts');
Stream<QuerySnapshot> dbStream(BuildContext context) async* {
final uid = await Provider.of(context).auth.getUidPref();
final intValues = await getValues();
yield* intValues == 1
? dbPath
.document(uid)
.collection('debts')
.orderBy('balance')
.snapshots()
: dbPath
.document(uid)
.collection('debts')
.orderBy('interest',descending: true)
.snapshots();
}
@override
void initState() {
super.initState();
restore();
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
RaisedButton(
child: Text('SORT'),onpressed: () {
showDialog(
barrierdismissible: false,context: context,builder: (BuildContext context) {
return StatefulBuilder(
builder: (context,setState) {
return AlertDialog(
title: Text('Sort Debts By:'),content: Column(
mainAxisSize: MainAxisSize.min,children: <Widget>[
RadioListTile(
value: 1,secondary: IconButton(
onpressed: () {
showDialog(
context: context,builder: (BuildContext context) {
return AlertDialog(
title: Text('Debt snowball:'),content: Text(
'This is an explanation of debt snowball'),actions: <Widget>[
FlatButton(
child: Text('OK'),onpressed: () {
Navigator.pop(context);
},)
],);
});
},icon: Icon(Icons.help_outline),title: Text('snowball'),groupValue: group,onChanged: (T) {
setState(() {
group = T;
debtValue = 1;
});
},RadioListTile(
value: 2,title: Text('Avalanche'),secondary: IconButton(
onpressed: () {},onChanged: (T) {
setState(() {
group = T;
debtValue = 2;
});
},)
],actions: <Widget>[
FlatButton(
onpressed: () async {
setState(() {
setValues();
});
Navigator.pop(context);
},child: Text('UPDATE'),FlatButton(
child: Text(
'CANCEL',style: TextStyle(color: Colors.red),onpressed: () {
Navigator.pop(context);
},);
},);
}).then((value) => setState(() {}));
},StreamBuilder<QuerySnapshot>(
stream: dbStream(context),builder: (context,snapshot) {
if (snapshot.hasData) {
final debts = snapshot.data.documents;
List<Widget> debtWidgets = [];
for (var debt in debts) {
final debtName = debt.data['name'];
final debtType = debt.data['type'];
final debtBalance = debt.data['balance'];
final debtDue = debt.data['due'].toDate();
final debtWidget = Card(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,children: <Widget>[
Text('$debtType'),Text('$debtName'),Text(DateFormat.MMMd().format(debtDue)),Text('$debtBalance'),FlatButton(
child: Text(
'DELETE',onpressed: () {
//When I delete a debt I need to update the 'debtMinimum' field in prefs and firestore
},)
],);
debtWidgets.add(debtWidget);
}
return Column(children: debtWidgets);
}
return Container();
}),);
}
}
我不反对尝试任何可行的技术。提升状态,提供者或其他任何东西(不需要完全重建体系结构(我知道这不是非常好的东西))。 我已经尝试了好几天来解决这个问题。任何帮助将不胜感激。谢谢
解决方法
您可以包装窗口小部件以使用StreamBuilder更新,然后在按下RaisedButton时将事件发送到流接收器。下面是简单的示例:
/// Some where in State class
class _SomeWidgetState extends State<SomeWidget> {
/// Stream controller which takes integer identifiers
StreamController<int> streamController;
/// Result stream which converts int to UpdatableObject via function
Stream<UpdatableObject> get stream => streamController.stream.asyncMap(_getObjectById);
/// Takes object identifier and returns corresponding object.
Future<UpdatableObject> _getObjectById(int id) {
...
return UpdatableObject();
}
@override
void initState() {
super.initState();
// Take from parent `Provider` widget
streamController = Provider.of<int>(context,listen: false);
// or create it here (depends on requirements)
//streamController = StreamController<int>.broadcast();
}
@override
Widget build(BuildContext context) {
return StreamBuilder<UpdatableObject>(
stream: stream,builder: (context,snapshot) {
if (snapshot.hasError) {
return Text(snapshot.error.toString();
}
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
// `snapshot.data` contains instance of `UpdatableObject`
return TheWidgetToBeUpdated(data: snapshot.data);
}
);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。