Issue
I'm trying to make a budget app where each budget has its own spending history. Each of those spending histories would have a variable called 'budgetName' which I can compile and total the amount of spending by using sqflite code as below.
return await db.rawQuery("select sum(budgetSpent) as total from spending where budgetName ='" + budgetTitle + "'");
and this works if I try to use a .then((value) {print(value);})
when calling the sqflite function and see the value of each budget's spendings in the debug console.
But the problem is that I need the 'budgetTitle' when calling the function so it can compare with the spending's 'budgetName' to get the total spending amount.
So what I have right now is I try to get the spending amount like below:
child: BudgetCard(
budgetName: budget.budgetName,
budgetSpent: '${Provider.of<SpendingDatabaseHelper>(context, listen: false).getSpecificSpending(budget.budgetName}',
maxBudget: currency.format(int.parse(budget.maxBudget)),
svgIcon: iconListBudgetCards[budget.iconValue],
color: colorSwatch[budget.colorValue],
percentage: 0.5),
),
But it only returns Instance of 'Future<dynamic>'
because it needs the 'await' before getting the value. But I couldn't find another way of doing this because it needs the 'budgetTitle' to be passed on.
Any help, ideas, or suggestions are highly appreciated! thank you in advance.
Here is the database code:
String? budgetSpendingAmount;
getSpecificSpending(budgetTitle) async {
dynamic result =
await SpendingDatabaseHelper.instance.getSpendingAmount(budgetTitle);
String a = result.toString();
debugPrint('A: $a');
if (a == '[{total: null}]') {
a = currency.format(int.parse('000'.trim()));
budgetSpendingAmount = a;
print(budgetSpendingAmount);
} else {
String? b = a.replaceAll(RegExp(r'[{\}\[\]\-]+'), '');
String c = b.substring(b.indexOf(":") + 1);
budgetSpendingAmount = currency.format(int.parse(c.trim()));
}
notifyListeners();
}
Future getSpendingAmount(String budgetTitle) async {
Database db = await instance.database;
return await db.rawQuery("select sum(budgetSpent) as total from spending where ='" + budgetTitle + "'");
}
Here is the full code of where I call the function to get the spending amount data:
Widget build(BuildContext context) {
return FutureBuilder<List<Budget>>(
future: Provider.of<BudgetDatabaseHelper>(context).getBudgets(),
/// Displaying the data from the list
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Center();
}
return snapshot.data!.isEmpty
? const Flexible(
child: Center(
child: Padding(
padding: EdgeInsets.only(bottom: 80.0),
child: Text(
'You don\'t have any budget',
style: kCaption,
),
)))
: Flexible(
child: ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
final budget = snapshot.data![index];
return Dismissible(
key: UniqueKey(),
background: const Align(
alignment: Alignment.centerRight,
child: Padding(
padding: EdgeInsets.only(bottom: 12.0, right: 24),
child: Icon(
IconlyLight.delete,
color: cRed,
size: 24,
),
),
),
direction: DismissDirection.endToStart,
onDismissed: (direction) {
snapshot.data!.removeAt(index);
Provider.of<BudgetDatabaseHelper>(context,
listen: false)
.removeMethod(budget.id!, budget.budgetName);
},
child: GestureDetector(
onTap: () => showModalBottomSheet(
backgroundColor: Colors.transparent,
context: context,
enableDrag: true,
isScrollControlled: true,
builder: (context) {
return DraggableScrollableSheet(
snap: true,
minChildSize: 0.43,
maxChildSize: 0.85,
initialChildSize: 0.43,
snapSizes: const [0.43, 0.85],
builder: (context, scrollController) {
return ClipRRect(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(32),
topRight: Radius.circular(32)),
child: Container(
color: cWhite,
child: SingleChildScrollView(
controller: scrollController,
physics: const BouncingScrollPhysics(),
child: BudgetDetails(
id: budget.id!,
budgetName: budget.budgetName,
budgetSpent: 'budgetSpent',
colorValue:
colorSwatch[budget.colorValue],
maxBudget: currency.format(
int.parse(budget.maxBudget)),
svgIcon: iconListBudgetDetails[
budget.iconValue],
),
),
),
);
},
);
},
),
child: BudgetCard(
budgetName: budget.budgetName,
budgetSpent: '${Provider.of<SpendingDatabaseHelper>(context, listen: false).getSpecificSpending(budget.budgetName}',
maxBudget: currency.format(int.parse(budget.maxBudget)),
svgIcon: iconListBudgetCards[budget.iconValue],
color: colorSwatch[budget.colorValue],
percentage: 0.5),
),
);
},
),
);
},
);
}
Solution
Use provider
in a widget tree is not a good idea. Make a statefullWidget
Make a getter in your SpendingDatabaseHelper
like this
String? _budgetSpendingAmount;
String get budgetSpendingAmount=> _budgetSpendingAmount;
and initialize it like this _budgetSpendingAmount = currency.format(int.parse(c.trim()));
So using this getter you can access this value anywhere in widget tree
Future<void> _getSpecificSpending(String budgetName)async{
try{
await Provider.of<SpendingDatabaseHelper>(context, listen: false).getSpecificSpending(budgetName);
} catch(e){
print('error :$e');
}
}
and in your widget tree write something like this
child: FutureBuilder(
future : _getSpecificSpending(budget.budgetName)
builder: (ctx,snapshot){
var spendDataProv=Provider.of<SpendingDatabaseHelper>(context, listen: false);
return snapshot.connectionState==ConnectionState.waiting ?
CircularProgressIndicator() :
BudgetCard(
budgetName: budget.budgetName,
budgetSpent:spendDataProv.budgetSpendingAmount ,
maxBudget: currency.format(int.parse(budget.maxBudget)),
svgIcon: iconListBudgetCards[budget.iconValue],
color: colorSwatch[budget.colorValue],
percentage: 0.5)
},
)
Answered By - Saddan
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.