Flutter : NoSuchMethodError: The method 'showSnackBar' was called on null - flutter

I got some problem with _showSnackbar I see following error:
Exception has occurred.
NoSuchMethodError (NoSuchMethodError: The method 'showSnackBar'
was called on null.Receiver: null
Tried calling: showSnackBar(Instance of 'SnackBar'))
But I'm sure I already created GlobalKey for ShowSnackbar :
final _scaffoldKey = GlobalKey<ScaffoldState>();
This is my function showsnackbar
void _showSnackBar(BuildContext context, String message, Color color) {
final snackBar = SnackBar(
duration: Duration(seconds: 1),
backgroundColor: color,
content: Text(message),
);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
This is how I call the showsnackbar
upload != 0 ? _showSnackBar(context,"Success Upload",Colors.green) : _showSnackBar(context,"Success Upload",Colors.green);
And this is the full source code my view
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:mosque/api/api_mosque.dart';
class UploadImage extends StatefulWidget {
#override
_UploadImageState createState() => _UploadImageState();
}
class _UploadImageState extends State<UploadImage> {
final _scaffoldKey = GlobalKey<ScaffoldState>();
ApiHelper api = ApiHelper();
File _image;
TextEditingController _txtNameImage = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_left),
onPressed: () => Navigator.pop(context, false),
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.file_upload),
onPressed: () {
uploadImageRevisi(_image,_txtNameImage);
},
)
],
),
body: _formUpload(),
);
}
Widget _formUpload() {
return SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: <Widget>[
TextField(
controller: _txtNameImage,
keyboardType: TextInputType.text,
decoration: InputDecoration(hintText: "Nama Image"),
maxLength: 9,
textAlign: TextAlign.center,
),
SizedBox(
height: 50.0,
),
Container(
child: _image == null
? Text('No Images Selected')
: Image.file(_image),
),
SizedBox(
height: 50.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Icon(Icons.camera),
onPressed: () => getImageCamera(),
),
SizedBox(
width: 50.0,
),
RaisedButton(
child: Icon(Icons.image),
onPressed: () => getImageGallery(),
)
],
)
],
),
);
}
void uploadImageRevisi(File imageFile, TextEditingController _txtName) async{
int upload = await api.uploadImageRevisi(imageFile,_txtName);
upload != 0 ? _showSnackBar(context,"Success Upload",Colors.green) : _showSnackBar(context,"Success Upload",Colors.green);
}
getImageGallery() async {
var imageFile = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
_image = imageFile;
});
}
getImageCamera() async {
var imageFile = await ImagePicker.pickImage(source: ImageSource.camera);
setState(() {
_image = imageFile;
});
}
void _showSnackBar(BuildContext context, String message, Color color) {
final snackBar = SnackBar(
duration: Duration(seconds: 1),
backgroundColor: color,
content: Text(message),
);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
}
Did I make a mistake somewhere?
Thanks

You've forgot to set key property:
return Scaffold(
key: _scaffoldKey ...

Related

Nasa API FLUTTER WITH pub.dev

| I used to crate an App on flutter wiht the Nasa API but i only get strings back, but i wanna have pictures in my App how do i get picturers from this strings ?
I already tried this but this but i dont finde the point where i coan change the program to give me the coice to macke a foto out of this String
import 'package:flutter/material.dart';
import 'package:nasa_apis/nasa_apis.dart';
import 'package:tuple/tuple.dart';
class ApodScreen extends StatefulWidget {
const ApodScreen({super.key, required this.title});
final String title;
#override
State<ApodScreen> createState() => _ApodScreenState();
}
class _ApodScreenState extends State<ApodScreen> {
static const String _widgetNasaApod = "APOD";
String _selected = _widgetNasaApod;
String _apodTestDescription =
"The request will appear here.";
List<ApodItem> _apodTestResults = <ApodItem>[];
#override
void initState() {
super.initState();
init();
}
void init() async {
await Nasa.init(
logReceiver: (String msg, String name) {
},
apodSupport: true,
apodCacheSupport: true,
apodDefaultCacheExpiration: const Duration(seconds: 20));
}
#override
Widget build(BuildContext context) {
List<Widget> widgets = <Widget>[];
if (_selected == _widgetNasaApod) {
widgets.add(
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
onPressed: () async {
_apodTestResults.clear();
DateTime date = DateTime.now();
Tuple2<int, ApodItem?> result =
await NasaApod.requestByDate(date);
_apodTestDescription =
"requestByDate()\ndate[${date.toString()}]\nhttp response code: ${result.item1.toString()}";
if (result.item2 != null) {
_apodTestResults.add(result.item2!);
}
setState(() {});
},
child: const Text("Today"),
),
TextButton(
onPressed: () async {
_apodTestResults.clear();
Tuple2<int, List<ApodItem>?> result =
await NasaApod.requestByRandom(5);
_apodTestDescription =
"requestByRandom()\ncount[5]\nhttp response code: ${result.item1.toString()}";
if (result.item2 != null) {
_apodTestResults = result.item2!;
}
setState(() {});
},
child: const Text("Random"),
),
TextButton(
onPressed: () async {
_apodTestResults.clear();
DateTime startDate = DateTime(2022, 10, 1);
DateTime endDate = DateTime(2022, 10, 31);
Tuple2<int, List<MediaType>?> result =
(await NasaApod.requestByRange(startDate, endDate)) as Tuple2<int, List<MediaType>?>;
_apodTestDescription =
"requestByOctober()\n$startDate - $endDate\nhttp response code: ${result.item1.toString()}";
if (result.item2 != null) {
_apodTestResults = result.item2!.cast<ApodItem>();
}
setState(() {});
},
child: const Text("October"),
),
],
),
);
widgets.add(Text(_apodTestDescription));
for (ApodItem apodItem in _apodTestResults) {
widgets.add(
Padding(
padding: const EdgeInsets.all(15),
child: Text(
apodItem.toString(),
),
),
);
}
}
return Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: (){
Navigator.of(context).pop();
}, icon: const BackButtonIcon(),
),
title: Text(widget.title),
),
body: SingleChildScrollView(
child: Column(
children: widgets,
),
),
);
}
}
Looking at the NASA API code, you can see the class ApodItem definition (Here).
So in this part of your code :
for (ApodItem apodItem in _apodTestResults) {
widgets.add(
Padding(
padding: const EdgeInsets.all(15),
//Here you create a text widget
child: Text(
apodItem.toString(),
),
),
);
}
replace the Text widget by an Image.network using the getImageUrl method of ApodItem. Like this :
for (ApodItem apodItem in _apodTestResults) {
widgets.add(
Padding(
padding: const EdgeInsets.all(15),
//Here you get the url from you APOD item and create an image widget
child: Image.network(
apodItem.getImageUrl(),
),
),
);
}
getImageUrl will provide you with a url of the image (or of the thumbnail of the video if relevant. And Image.network will build the widget from the said url.

getx obx not updating avatar image - Flutter GetX

what I want to achieve is to change the image in CircleAvatar when I'm selecting an image, here is the code:
ProfileController:
class ProfileController extends GetxController {
final TextEditingController emailController = TextEditingController();
final ImagePicker _picker = ImagePicker();
Rx<String?> avatarPath = null.obs;
avatarFromCamera() async {
var localAvatar = await _picker.pickImage(
source: ImageSource.camera, imageQuality: 50
);
if (localAvatar != null) {
avatarPath = localAvatar.path.obs;
update();
}
}
avatarFromGallery() async {
var localAvatar = await _picker.pickImage(
source: ImageSource.gallery, imageQuality: 50
);
if (localAvatar != null) {
avatarPath = localAvatar.path.obs;
update();
}
}
String? emailValidator(String? value) {
if (value == null || value.isEmpty) {
return null;
}
if (!EmailValidator.validate(value, false)) {
return 'Invalid email address';
}
}
#override
void onClose() {
emailController.dispose();
super.onClose();
}
String? emailValidator(String? value) {
if (value == null || value.isEmpty) {
return null;
}
if (!EmailValidator.validate(value, false)) {
return 'Invalid email address';
}
}
void save(GlobalKey<FormState> profileFormKey) {
if (profileFormKey.currentState!.validate()) {
print('valid');
}
}
}
and here is the ProfileScreen widget:
lass ProfileScreen extends StatelessWidget {
final ProfileController _profileController = Get.put<ProfileController>(ProfileController());
GlobalKey<FormState> profileFormKey = GlobalKey<FormState>();
ProfileScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Update user details'),
),
body: SingleChildScrollView(
child: Form(
key: profileFormKey,
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(30.0),
child: TextFormField(
keyboardType: TextInputType.text,
controller: _profileController.emailController,
decoration: const InputDecoration(
labelText: 'Enter email',
),
validator: _profileController.emailValidator,
),
),
Center(
child: GestureDetector(
onTap: () {
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return SafeArea(
child: Wrap(
children: <Widget>[
ListTile(
leading: const Icon(Icons.photo_library),
title: const Text('Photo Library'),
onTap: () {
_profileController.avatarFromGallery();
Navigator.of(context).pop();
}),
ListTile(
leading: const Icon(Icons.photo_camera),
title: const Text('Camera'),
onTap: () {
_profileController.avatarFromCamera();
Navigator.of(context).pop();
},
),
],
),
);
}
);
},
child: CircleAvatar(
radius: 55,
backgroundColor: Colors.pink,
child: Obx(() =>(_profileController.avatarPath.value != null)
? ClipRRect(
borderRadius: BorderRadius.circular(50),
child: Image.file(
File(_profileController.avatarPath.value!),
width: 100,
height: 100,
fit: BoxFit.fitHeight
),
)
: Container(
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(50)),
width: 100,
height: 100,
child: Icon(
Icons.camera_alt,
color: Colors.grey[800],
),
),
),
),
)),
Container(
margin: const EdgeInsets.all(10),
width: double.infinity,
child: MaterialButton(
color: Colors.blue,
onPressed: () => _profileController.save(profileFormKey),
child: const Text(
'Submit',
style: TextStyle(color: Colors.white),
),
),
),
],
),
),
),
);
}
}
as you can see, I have Obx and my avatarPath reactive, and I'm running update everywhere I changing it, but it's not udpated. I also tried to use empty string as initial value of imagePath like this Rx<String> avatarPath = ''.obs; and it's not working. What I'm doing wrong??? Thank you in advice!!!
There are two things to revise for it. Firstly, change avatarPath = localAvatar.path.obs; with avatarPath.value = localAvatar.path;. Because localAvatar.path.obs create the new observable and changes will not be reflected to previous observers.
Secondly, create a new stateless widget having the widget tree of bottom sheet's builder like
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return CustomBottomView();
}
);
Then inside the CustomBottomView copy your bottom sheet widget tree.
class CustomBottomView extends GetView<ProfileController> {
return YourBottomSheetWidgetTreeHere();
}
Dont worry about ProfileController here. You have already put it in DI in previous route. First follow the first step if you still face the problem second step will definitely resolve it.

How to deal with infinite size

I was coding my flutter project when I fall under this error. I do not understand because I have tried all the available solution online and still it is not working. The craziest thing is I have the exact same code on the other page and it is working perfectly.
And If I restart the app it works. The first problem was a Material app which is the main function and even if I wrap the column with a scaffold it still doesn't work
Below is the error
The following assertion was thrown during performLayout():
RenderCustomMultiChildLayoutBox object was given an infinite size during layout.
This probably means that it is a render object that tries to be as big as possible, but it was put inside another render object that allows its children to pick their own size.
The nearest ancestor providing an unbounded height constraint is: _RenderSingleChildViewport#20590 relayoutBoundary=up10 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
... needs compositing
... parentData: <none> (can use size)
... constraints: BoxConstraints(w=358.0, 0.0<=h<=731.0)
... layer: OffsetLayer#17148
... engine layer: OffsetEngineLayer#48e1c
... handles: 2
... offset: Offset(16.0, 63.0)
... size: Size(358.0, 731.0)
The constraints that applied to the RenderCustomMultiChildLayoutBox were: BoxConstraints(0.0<=w<=358.0, 0.0<=h<=Infinity)
The exact size it was given was: Size(358.0, Infinity)
Below this I have form that receives data from another one
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:loading_overlay/loading_overlay.dart';
import 'package:tembea/components/rounded_button.dart';
import 'package:tembea/components/show_toast.dart';
import 'package:tembea/components/time_pick.dart';
import 'package:tembea/screens/admin/admin_screens/restaurant/dashboard_restaurant.dart';
import '../../../../../constants.dart';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:tembea/components/square_button.dart';
import 'dart:io' ;
import 'package:firebase_storage/firebase_storage.dart';
import 'add_images.dart';
class RestaurantSecondaryForm extends StatefulWidget {
const RestaurantSecondaryForm({
Key? key,
required this.name,
required this.location,
required this.price,
required this.description,
}) : super(key: key);
final String name;
final String location;
final String price;
final String description;
#override
_RestaurantSecondaryFormState createState() => _RestaurantSecondaryFormState();
}
class _RestaurantSecondaryFormState extends State<RestaurantSecondaryForm> {
bool showSpinner = false;
String selectedOpeningTime = '8:00 AM';
String selectedClosingTime = '17:00 PM';
String ? selectedTime;
final List<String> defaultImageList = [
'assets/images/image.png',
'assets/images/image.png',
'assets/images/image.png',
];
List<String> imageList =[];
List<File> files = [];
List<String> ? imageUrl;
TaskSnapshot? snap;
String ? photoUrl;
String ? photoUrl2;
String ? photoUrl3;
String selectedType = 'Restaurant';
#override
Widget build(BuildContext context) {
Future<void> openTimePicker(context) async {
final TimeOfDay? t =
await showTimePicker(
context: context, initialTime: TimeOfDay.now());
if(t != null){
setState(() {
selectedTime = t.format(context);
});
}
}
goToAddImage() async{
List<String> imgUrl = await Navigator.push(context, MaterialPageRoute(builder:(context){
return const AddImages();
}));
setState(() {
imageUrl = imgUrl;
});
}
if(imageUrl?.isNotEmpty == true){
setState(() {
photoUrl = imageUrl?[0];
photoUrl2 = imageUrl?[1];
photoUrl3 = imageUrl?[2];
imageList.add(photoUrl!);
imageList.add(photoUrl2!);
imageList.add(photoUrl3!);
});
}
else{
setState(() {
photoUrl = '';
photoUrl2 = '';
photoUrl3 = '';
});
}
return LoadingOverlay(
isLoading: showSpinner,
opacity: 0.5,
color: Colors.green,
progressIndicator: const CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation(Colors.green),
),
child: Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: const Text('Add Restaurant'),
backgroundColor: kBackgroundColor.withOpacity(0.3),
),
body: Padding(
padding: const EdgeInsets.all(40.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CarouselSlider(
options: CarouselOptions(
enlargeCenterPage: true,
enableInfiniteScroll: false,
autoPlay: false,
),
items:imageList.isEmpty ? defaultImageList.map((e) => ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Stack(
fit: StackFit.expand,
children: [
Image.asset(
e,
width: 1000,
height: 300,
fit: BoxFit.fill,
)
],
),
)).toList()
: imageList.map((e) => ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Stack(
fit: StackFit.expand,
children: [
Image.network(
e,
width: 1000,
height: 300,
fit: BoxFit.fill,
)
],
),
)).toList(),
),
const SizedBox(
height: 20,
),
Column(
children: [
DateButton(
text: 'Upload Images',
onPressed: () {
goToAddImage();
},
),
],
),
Column(
children: [
TimePick(
label: 'Opens at',
labelColor: Colors.green,
time: selectedOpeningTime,
onPressed: (){
openTimePicker(context).then((value) {
setState(() {
selectedOpeningTime = selectedTime!;
});
});
},
),
const SizedBox(
height: 20,
),
TimePick(
label: 'Closes at',
labelColor: Colors.red,
time: selectedClosingTime,
onPressed: (){
openTimePicker(context).then((value) {
setState(() {
selectedClosingTime = selectedTime!;
});
});
}
),
],
),
RoundedButton(
buttonName: 'Add Restaurant',
color: Colors.green,
onPressed: () async{
setState(() {
showSpinner = true;
});
final time = DateTime.now();
await FirebaseFirestore.instance.collection('activities').doc().set({
'Name' : widget.name,
'Location': widget.location,
'Description' : widget.description,
'Price' : widget.price,
'OpeningTime' : selectedOpeningTime,
'ClosingTime' : selectedClosingTime,
'PhotoUrl' : photoUrl,
'PhotoUrl2' : photoUrl2,
'PhotoUrl3' : photoUrl3,
'Type' : selectedType,
'ts' : time,
}).then((value) {
setState(() {
showSpinner = false;
});
showToast(message: 'Restaurant Added',
color: Colors.green
);
Navigator.pushNamedAndRemoveUntil(context, DashboardRestaurant.id, (r) => false);
});
}
),
],
),
),
),
);
}
}
which is supposed to navigate back to this view that brings the error
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:tembea/components/add_button.dart';
import 'package:tembea/components/responsive.dart';
import 'package:tembea/components/show_dialog.dart';
import 'package:tembea/components/show_toast.dart';
import 'package:tembea/screens/admin/admin_screens/view_data.dart';
import 'event_form.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/foundation.dart';
class DashboardEvent extends StatefulWidget {
const DashboardEvent({Key? key}) : super(key: key);
static String id = 'dashboard_event';
#override
_DashboardEventState createState() => _DashboardEventState();
}
class _DashboardEventState extends State<DashboardEvent> {
final Stream<QuerySnapshot> activities = FirebaseFirestore
.instance.collection('activities')
.where('Type', isEqualTo: 'Event')
.orderBy('ts', descending: true)
.snapshots();
#override
Widget build(BuildContext context) {
return Column(
children: [
AddButton(
title: 'Events',
addLabel: 'Add Events',
onPressed: (){
Navigator.pushNamed(context, EventForm.id);
},),
const SizedBox(
height: 16.0,
),
const Divider(
color: Colors.white70,
height:40.0,
),
StreamBuilder<QuerySnapshot>(
stream: activities,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot){
if(snapshot.connectionState == ConnectionState.waiting){
return const Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation(Colors.green),
),
);
}
final data = snapshot.requireData;
if(data != null){
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: data.size,
itemBuilder: (context, index){
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CircleAvatar(
backgroundColor: Colors.transparent,
radius: 40,
child:Image.network(
data.docs[index]['PhotoUrl'],
),
),
Text( data.docs[index]['Name'], style:const TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold),
),
if(Responsive.isWeb(context))
const SizedBox(
width: 50,
),
Responsive.isWeb(context) ? ButtonBlue(
addLabel: 'View Event',
color: Colors.green,
onPressed: (){
Navigator.push(context, MaterialPageRoute(builder: (context){
return ViewData(item: data.docs[index],);
}));
},
icon: const Icon(IconData(61161, fontFamily: 'MaterialIcons')),
) : InkWell(
onTap: (){
Navigator.push(context, MaterialPageRoute(builder: (context){
return ViewData(item: data.docs[index],);
}));
},
child: const Icon(IconData(61161, fontFamily: 'MaterialIcons')),
),
Responsive.isWeb(context) ? ButtonBlue(
addLabel: 'Delete Event',
color: Colors.red,
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context){
return ShowDialog(
deleteFunction: () async{
await FirebaseFirestore.instance.runTransaction((Transaction myTransaction) async {
FirebaseStorage.instance.refFromURL(data.docs[index]['PhotoUrl']).delete();
myTransaction.delete(snapshot.data!.docs[index].reference);
}).then((value) => Navigator.pop(context));
},
dialogTitle: "Delete",
dialogContent: "Do you really want to delete ${data.docs[index]['Name']} event?",
);
});
},
icon: const Icon(Icons.delete_outline,),
): InkWell(
onTap: (){
if(defaultTargetPlatform == TargetPlatform.iOS){
showCupertinoDialog(
context: context,
builder: (BuildContext context){
return ShowDialog(
deleteFunction: () async{
await FirebaseFirestore.instance.runTransaction((Transaction myTransaction) async {
FirebaseStorage.instance.refFromURL(data.docs[index]['PhotoUrl']).delete();
myTransaction.delete(snapshot.data!.docs[index].reference);
}).then((value) => Navigator.pop(context));
},
dialogTitle: "Delete",
dialogContent: "Do you really want to delete ${data.docs[index]['Name']} event?",
);
});
}
else if((defaultTargetPlatform == TargetPlatform.android)){
showDialog(
context: context,
builder: (BuildContext context){
return ShowDialog(
deleteFunction: () async{
await FirebaseFirestore.instance.runTransaction((Transaction myTransaction) async {
FirebaseStorage.instance.refFromURL(data.docs[index]['PhotoUrl']).delete();
myTransaction.delete(snapshot.data!.docs[index].reference);
}).then((value) => Navigator.pop(context));
},
dialogTitle: "Delete",
dialogContent: "Do you really want to delete ${data.docs[index]['Name']} event?",
);
});
}
else{
showDialog(
context: context,
builder: (BuildContext context){
return ShowDialog(
deleteFunction: () async{
await FirebaseFirestore.instance.runTransaction((Transaction myTransaction) async {
FirebaseStorage.instance.refFromURL(data.docs[index]['PhotoUrl']).delete();
myTransaction.delete(snapshot.data!.docs[index].reference);
Navigator.pop(context);
showToast(message: 'Deleted Successfully', color: Colors.green);
}).then((value) => Navigator.pop(context));
},
dialogTitle: "Delete",
dialogContent: "Do you really want to delete ${data.docs[index]['Name']} event?",
);
});
}
},
child: const Icon(Icons.delete_outline,),
),
],
),
const Divider(
color: Colors.white70,
height:40.0,
),
],
);
});
}
return const Center(
child: CircularProgressIndicator(),
);
},
)
],
);
}
}
I have been on this the entire day but in vain but in the same product, I have another view details with the same code that works
Please assist me on this

type 'Future<dynamic>' is not a subtype of type '() => void' flutter

════════ Exception caught by widgets library ═══════════════════════════════════
The following _TypeError was thrown building ProfileEdit(dirty, state: _ProfileEditState#eb2ff):
type 'Future' is not a subtype of type '() => void'
Please let me know where did I went wrong, I am new to Flutter.
Can you help with the subject?
class ProfileEdit extends StatefulWidget {
final Users profile;
const ProfileEdit({Key key, this.profile}) : super(key: key);
#override
_ProfileEditState createState() => _ProfileEditState();
}
class _ProfileEditState extends State<ProfileEdit> {
var _formKey = GlobalKey<FormState>();
String _userName;
File _valuePhoto;
bool _loading = false;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.grey,
title: Text(
"Profili Düzenle",
style: TextStyle(color: Colors.black),
),
leading: IconButton(
icon: Icon(
Icons.close,
color: Colors.black,
),
onPressed: () => Navigator.pop(context)),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.check,
color: Colors.black,
),
onPressed: _save()),
],
),
body: ListView(
children: <Widget>[
_loading
? LinearProgressIndicator()
: SizedBox(
height: 0.0,
),
_profilePhoto(),
_userInfo(),
],
),
);
}
_save() async {
if (_formKey.currentState.validate()) {
setState(() {
_loading = true;
});
_formKey.currentState.save();
String profilePhotoUrl;
if (_valuePhoto == null) {
profilePhotoUrl = widget.profile.photoUrl;
} else {
profilePhotoUrl = await StorageService().profilePhotoAdd(_valuePhoto);
}
String activeUserId =
Provider.of<AuthorizationService>(context, listen: false)
.activeUserId;
//veritabanına güncel verileri eklemek için.
FireStoreService().userUpdate(
userId: activeUserId, userName: _userName, photoUrl: profilePhotoUrl);
setState(() {
_loading = false;
});
Navigator.pop(context);
}
}
_profilePhoto() {
return Padding(
padding: const EdgeInsets.only(top: 15.0, bottom: 20.0),
child: Center(
child: InkWell(
onTap: _galleryChoose,
child: CircleAvatar(
backgroundColor: Colors.grey,
backgroundImage: _valuePhoto == null
? NetworkImage(widget.profile.photoUrl)
: FileImage(_valuePhoto), //galeriden fotoğraf ekleme.
radius: 55.0,
),
),
),
);
}
_galleryChoose() async {
var image = await ImagePicker().getImage(
source: ImageSource.gallery,
maxWidth: 800,
maxHeight: 600,
imageQuality: 80);
setState(() {
_valuePhoto = File(image.path);
});
}
_userInfo() {
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 120.0,
),
child: Form(
child: Column(
children: <Widget>[
SizedBox(
height: 20.0,
),
TextFormField(
//varsayılan kullanıcı adı düzenleme ekranında da gözükmesi için initialvalue çalışıyor.
initialValue: widget.profile.userName,
decoration: InputDecoration(labelText: "Kullanıcı Adı"),
validator: (inputValue) {
return inputValue.trim().length <= 3
? "Kullanıcı Adı en az 4 karakter olmalı."
: null;
},
onSaved: (inputValue) {
_userName = inputValue;
},
),
],
),
),
);
}
}
instead of
_save() async {
try using
Future _save() async {
The onPressed property of a button needs a function that has a return type of void, and every function that is marked as async will always have a return type of some kind of Future. To get around this, you can wrap passing _save to the button in a lambda function:
onPressed: () => _save(),

Updating state in flutter

I have a dialog box that sorts a list on my home screen. When I press update the list will sort properly.
What I need to do is run setState for the entire home screen so that the other widgets will reflect the change for the sort order.
Specifically, I have two widgets that I need to rebuild when the update button is pressed.
I have tried to pass a function from the button to the home screen in the constructor and created a function to setState but that didn't work.
Please let me know if I'm being clear enough. Thanks
Home:
#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(),
SizedBox(height: 30),
//parent
MainDebtDebt(),
SizedBox(height: 30),
AdCard(),
//child
AllDebtsCard(),
All debts card (where the button is):
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: () {},
icon: Icon(Icons.help_outline),
),
groupValue: group,
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',
style: TextStyle(color: Colors.red),
),
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();
}),
],
);
}
}
One of the two widgets that I need updated:
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'),
],
),
SizedBox(
height: 15,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(getGoalType ? 'Remaining Balance:' : 'Saved:'),
SizedBox(
width: 15,
),
Text(getGoalType
? '\$' + balance.toStringAsFixed(0)
: safetyBalance.toStringAsFixed(0))
],
),
SizedBox(
height: 15,
),
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('mainAvalancheBalanceType1');
//pref.setBool('isInOb', null);
print(thenum);
},
),
],
)
],
),
);
}
}