Flutter: Unable to refetch image after updated image in Firebase - flutter

Previously in my log in page, I prompted user to upload a profile image, then the user is able to edit their profile picture by re-upload another new profile image. However, once the user selected the new image, the link is able to update on the Firebase side but the new link image requires hot reload in order to reflect the new image on the page. Anyone knows a better solution to it? My pick image function:
Future pickImage(ImageSource source) async {
try {
final image = await ImagePicker().pickImage(source: source);
if (image == null) return;
setState(() => _imageFile = File(image.path));
String fileName = Path.basename(_imageFile!.path);
Reference firebaseStorageRef =
FirebaseStorage.instance.ref().child('$fileName');
await firebaseStorageRef.putFile(File(image.path));
setState(() async {
imageUrl = await firebaseStorageRef.getDownloadURL();
await FirebaseFirestore.instance
.collection('MerchantData')
.doc(widget.currentUser?.uid)
.update({"shopLogo": imageUrl}).then((value) => {
showFlash(
context: context,
duration: const Duration(seconds: 2),
builder: (context, controller) {
return Flash.bar(
controller: controller,
backgroundColor: Colors.green,
position: FlashPosition.top,
child: Container(
width: MediaQuery.of(context).size.width,
height: 70,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"Shop Logo Updated Successfully",
style: const TextStyle(
color: Colors.white,
fontSize: 18,
),
),
],
)),
);
},
)
});
});
} on PlatformException catch (e) {
print("Failed to pick image: $e");
}
}
Here is the FutureBuilder I used to display the image:
FutureBuilder(
future: getData(),
builder: (BuildContext context, snapshot) {
imageUrl = (snapshot.data as Map<String, dynamic>)['shopLogo'];
if (snapshot.hasData) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
],
);
} else {
return Column(children: [
Container(
margin: EdgeInsets.fromLTRB(0, 10.0, 0, 20),
child: CircleAvatar(
radius: 50.0,
child: ClipRRect(
child: Image(
height: 100,
width: 100,
image: NetworkImage(imageUrl),
fit: BoxFit.fill,
),
borderRadius: BorderRadius.circular(50.0),
),
),
),
GestureDetector(
onTap: () {
showMyDialog();
},
child: Container(
margin: EdgeInsets.fromLTRB(0, 0, 0, 30),
child: Text(
"Change Logo Photo",
style: const TextStyle(
color: Colors.blue,
fontSize: 16,
),
),
),
),
]);
}
} else if (snapshot.hasError) {
return Text('no data');
}
return CircularProgressIndicator();
},
),
and here is my getData() function:
getData() async {
var firestore = FirebaseFirestore.instance;
DocumentSnapshot qn = await firestore
.collection('MerchantData')
.doc(widget.currentUser?.uid)
.get();
return qn.data();
}

Related

Flutter: get a document from Firestore inside a widget that returns a Widget

In my build I have this StreamBuilder which will get the data of the posts
and map it into a method that will return a widget to build the posts
StreamBuilder<List<Post>>(
stream: readPosts(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
if (snapshot.data == null) {
print(snapshot.error.toString());
return Text(snapshot.error.toString());
} else {
final posts = snapshot.data;
print('from streambuilder');
return Column(
children: posts!.map(buildPost).toList(),
);
}
} else {
return Center(
child: CircularProgressIndicator(),
);
}
})
this is the readPosts function that provides the stream of the posts
Stream<List<Post>> readPosts() {
return FirebaseFirestore.instance
.collection('posts')
.where('availableFor', whereIn: ['All', 'Business Adminstration'])
.snapshots()
.map((snapshot) {
// print(snapshot);
return snapshot.docs.map((doc) {
// print(doc.data());
return Post.fromJson(doc.data());
}).toList();
});
}
and then the the list of posts are mapped into the buildPost function which will return the post widget
Widget buildPost(Post post) {
final organizations = getUserData(post.owner) //I want this final property to get an
Organization value as a return type
// however it is returning a Future<Organizations>
value
//is there any way I can use to convert
it to an Organizations type?
//and I want to keep this function as a
widget so that the stream builder
//does not give me an error
return Container(
padding: EdgeInsets.all(10),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8.0))),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(8.0),
topRight: Radius.circular(8.0),
),
child: Image.network(post.imageUrl,
loadingBuilder: ((context, child, loadingProgress) {
return loadingProgress == null
? child
: LinearProgressIndicator();
}), height: 200, fit: BoxFit.fill
),
),
ListTile(
isThreeLine: true,
subtitle: Text(
'valid until: ${post.validUntil} for ${post.availableFor}',
style: TextStyle(
fontSize: 12,
color: Colors.grey.shade400,
fontWeight: FontWeight.bold),
),
leading: ClipOval(
child: Container(
height: 30,
width: 30,
child: Image.network(organizations!.imageUrl,
loadingBuilder: ((context, child, loadingProgress) {
return loadingProgress == null
? child
: LinearProgressIndicator();
}), height: 200, fit: BoxFit.fill
),
),
),
title: Text(
post.description,
style: TextStyle(fontSize: 14),
),
trailing: Text(organizations!.id),
)
],
),
),
);
}
this is the getUserData function
Future<Organizations> getUserData(organizationId) async {
var organizations;
await FirebaseFirestore.instance
.collection('organizations')
.where('id', isEqualTo: organizationId)
.get()
.then((event) {
if (event.docs.isNotEmpty) {
Map<String, dynamic> documentData =
event.docs.single.data(); //if it is a single document
print(documentData.toString());
organizations = Organizations.fromJson(documentData);
}
}).catchError((e) => print("error fetching data: $e"));
return organizations;
}
is there a way to use the organizations data in build post method?

Flutter : Why future builder don't run what inside snapshot.hasData? Edited

I made many test apps but this time I don't know why I get this error :
I have this Future function with future builder inside state less widget :
Future<List> getDegrees() async {
var url =
'https://xxxxxx/api/controller/activities/activiy_list.php?d_id=$dId&m_id=$courseId&u_id=$uId';
var response = await http.get(url);
var data = jsonDecode(response.body);
for (var x in data) {
Digree newdigree = Digree(
x['index'],
x['title_k'],
x['title_a'],
x['aya'],
x['link'],
x['activity_k'],
x['activity_a'],
x['act_id'],
x['mydigree']);
digrees.add(newdigree);
}
return digrees;
}
return FutureBuilder(
future: getDegrees(),
// ignore: missing_return
builder: (context, snapshot) {
if (snapshot.hasError || snapshot.data == null) {
return WillPopScope(
// ignore: missing_return
onWillPop: () async {
Navigator.of(context)
.pushReplacementNamed('weeks', arguments: {
'courseId': courseId,
});
},
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.pink[900],
title: Text(
'ژیان و قورئان',
style: TextStyle(fontSize: 32),
),
centerTitle: true,
),
body: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
image: DecorationImage(
image:
AssetImage('./assets/images/background.png'),
fit: BoxFit.cover)),
child: Column(
children: [
SizedBox(
height: 100,
),
Container(
height: 100,
width: 100,
child: CircularProgressIndicator(
backgroundColor: Colors.black,
strokeWidth: 5,
),
),
SizedBox(
height: 20,
),
Text(
"Loading ......",
style: TextStyle(color: Colors.white, fontSize: 18),
)
],
),
)));
} else if (snapshot.hasData) {
return WillPopScope(
// ignore: missing_return
onWillPop: () async {
Navigator.of(context)
.pushReplacementNamed('weeks', arguments: {
'courseId': courseId,
});
},
child: Scaffold(body: Container(child: Text('welcome'))));
}
});
I checked many time I didn't found my mistake , When I print the received list inside the function it is print correctly ,but when I display it in future builder it don't work ,where is my problem ?
The problem is : Future Builder just run CircularProgressIndicator .
Any Help?

How to Hide a card in flutter

I make one page to edit data by user.In this page I have two card.In the first card, I can see the user's picture.In the second card, I can see the user’s picture after selecting them from the phone or the picture they want to update.But now my problem is, how can I hide the first card if the second card appears after the user selects an image from the phone.I know it can be done by using Visibility in Java, but I'm a new filter developer and I don't know how to do it. I searched a lot and couldn't solve the problem.
Card 1:
child: Card(
child: new Column(
children: <Widget>[
Image.network(image, width: 385,height: 300,
fit: BoxFit.cover,
),
OutlineButton(
onPressed: chooseImage,
child: Text('Choose Image'),
),
])
),
Card 2:
Card(
child: SizedBox(
width: 400.0,
height: 300.0,
child: new Padding(
padding:
const EdgeInsets.only(top: 2.0, bottom: 2.0),
child: Expanded(flex: 1,
child: showImage(),
)
),
),
),
Full page:
class update_profilettt extends StatefulWidget {
var PostID;
update_profilettt({Key key, this.PostID}) : super(key: key);
#override
_update_profiletttState createState() => new _update_profiletttState(PostID);
}
class _update_profiletttState extends State<update_profilettt> {
MyPreferences _myPreferences = MyPreferences();
var PostID;
String uploadEndPoint;
_update_profiletttState(this. PostID);
Future<File> file;
String status = '';
String base64Image;
File tmpFile;
String errMessage = 'Error Uploading Image';
var data;
var _name = "";
// var _genderController = new TextEditingController();
var _nameController = new TextEditingController();
chooseImage() {
setState(() {
file = ImagePicker.pickImage(source: ImageSource.gallery);
});
setStatus('');
}
setStatus(String message) {
setState(() {
status = message;
});
}
startUpload() {
setStatus('Uploading Image...');
if (null == tmpFile) {
setStatus(errMessage);
return;
}
String NameImage =DateTime.now().millisecondsSinceEpoch.toString();
upload(NameImage);
}
upload(String NameImage) {
uploadEndPoint = 'http://xxxxxxx/up.php?id='+widget.PostID.toString();
print('yeyyyyddyy $uploadEndPoint');
http.post(uploadEndPoint, body: {
'id': widget.PostID.toString(),
}).then((result) {
setStatus(result.statusCode == 200 ? result.body : errMessage);
}).catchError((error) {
setStatus(error);
});
}
Widget showImage() {
return FutureBuilder<File>(
future: file,
builder: (BuildContext context, AsyncSnapshot<File> snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
null != snapshot.data) {
tmpFile = snapshot.data;
base64Image = base64Encode(snapshot.data.readAsBytesSync());
return Flexible(
child: Card(
margin:EdgeInsets.all(10) ,
child: Image.file(
snapshot.data,
fit: BoxFit.cover,
),
),
);
} else if (null != snapshot.error) {
return const Text(
'Error Picking Image',
textAlign: TextAlign.center,
);
} else {
return const Text(
'',
textAlign: TextAlign.center,
);
}
},
);
}
Future<String> _ShowDialog(String msg) async {
return showDialog<String>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return new AlertDialog(
title: new Text('Rewind and remember'),
content: new SingleChildScrollView(
child: new ListBody(
children: <Widget>[
new Text(msg),
],
),
),
actions: <Widget>[
new FlatButton(
child: new Text('Close'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
void _editData() async {
// String NameImage =DateTime.now().millisecondsSinceEpoch.toString();
var url = 'http://xxxxxxxxxx/up.php?id='+widget.PostID.toString();
var response = await http.post(url, body: {
'id': widget.PostID.toString(),
// "id": _userController.text,
"name": _nameController.text,
"image": base64Image,
// "gender": _genderController.text,
});
if (response.statusCode == 200) {
_ShowDialog("Updated Successfully");
} else {
_ShowDialog("Updated Failer");
}
//onEditedAccount();
//print(_adresseController.text);
}
_fetchData() async {final url = "http://xxxxxxxx/nhy.php?id=${widget.PostID}";
final response = await http.get(url);
if (response.statusCode == 200) {
final map = json.decode(response.body);
final videosMap = map["result"];
setState(() {
this.data = videosMap;
_name = data[0]['name'];
image = data[0]['image'];
// _gender = data[0]['gender'];
print(data);
});
}
}
#override
void initState() {
super.initState();
_fetchData();
}
#override
Widget build(BuildContext context) {
_nameController= new TextEditingController(text: _name);
if(chooseImage !=null){
}
return new Scaffold(
appBar: AppBar(
title: Text("Edit Post"),
),
body: new Center(
child: data == null
? new CircularProgressIndicator()
: new ListView(
children: <Widget>[
new Padding(
padding: const EdgeInsets.fromLTRB(5, 10, 5, 5),
child: Column(
children: <Widget>[
new Padding(
padding:
const EdgeInsets.only(top: 10.0, bottom: 10.0),
child: Expanded(flex: 1,
child: Container(
child: Card(
child: new Column(
children: <Widget>[
Image.network(image, width: 385,height: 300,
fit: BoxFit.cover,
),
OutlineButton(
onPressed: chooseImage,
child: Text('Choose Image'),
),
])
),
),
),
),
Card(
child: SizedBox(
width: 400.0,
height: 300.0,
child: new Padding(
padding:
const EdgeInsets.only(top: 2.0, bottom: 2.0),
child: Expanded(flex: 1,
child: showImage(),
)
),
),
),
Card (
child: Column(
children: <Widget>[
SizedBox(
height: 10.0,
),
Container(
margin: EdgeInsets.all(4),
child: TextField(
maxLength: 10,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Name',
filled: true,
hintText: ''),
controller: _nameController,
),
),
SizedBox(
height: 5.0,
),
),
SizedBox(
height: 5.0,
),
),
),
),
),
SizedBox(
height: 5.0,
),
]
)
),
SizedBox(
width: double.infinity,
child: new FlatButton(
child: const Text('Update'),color: Colors.amber,
padding: EdgeInsets.fromLTRB(100, 18, 100, 18),
onPressed: () { _editData();
},
),
),
SizedBox(
height: 10.0,
),
],
),
)
],
),
));
}
}
There is a Visibility widget in flutter too you can wrap your card with it
Example
bool visibilityController = true;
true for visibile and false for not visible
so when select the card use setstate to toggle it.
setState(() {
});
Visibility(
visible: visibilityController,
child : //Your card
),
Hope this is what you wished for.
For your code
you can do this when your showimage() gets an image
Widget showImage() {
return FutureBuilder<File>(
future: file,
builder: (BuildContext context, AsyncSnapshot<File> snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
null != snapshot.data) {
tmpFile = snapshot.data;
base64Image = base64Encode(snapshot.data.readAsBytesSync());
setState(() {
// added here
visibilityController = false;
});
return ........ your code

Using a CachedVideoPlayer in a listview

I am attempting to show videos in a listview that is preventing me from declaring the videocontroller in the initState. This causes me to accidentally be redrawing the video multiple times during the application. I am receiving this error:
FATAL EXCEPTION: ExoPlayerImplInternal:Handler
then
java.lang.OutOfMemoryError: OutOfMemoryError thrown while trying to throw OutOfMemoryError; no stack trace available
with my current implementation. It appears to work fora while but the memory slowly builds up until it is full. How can I implement this differently?
here is the code I am calling in the stream:
Widget getVideoItem(DocumentSnapshot doc) {
if (watchList.contains(doc['user'])) watched = true;
DateTime dateTime = DateTime.parse(doc['time']);
_videoPlayerController = CachedVideoPlayerController.network(doc["downUrl"])
..initialize();
_videoPlayerController.setLooping(true);
_videoPlayerController.play();
volumeOn = sharedPreferences.getBool("vidVol");
if (volumeOn == null) {
sharedPreferences.setBool("vidVol", false);
volumeOn = false;
}
if (volumeOn) {
_videoPlayerController.setVolume(1.0);
} else {
_videoPlayerController.setVolume(0.0);
}
return new FutureBuilder(
future: getUserData(doc["user"]),
builder: (BuildContext context, snapshot) {
return SizedBox(
height: MediaQuery.of(context).size.width + 140,
width: MediaQuery.of(context).size.width,
child: Column(children: <Widget>[
new ListTile(
title: new Text(userInfo),
subtitle: new Text(doc["title"]),
leading: FutureBuilder(
future: getProfUrl(doc),
builder: (BuildContext context, snapshot) {
Widget child;
if (!snapshot.hasData) {
child = _showCircularProgress();
} else {
child = child = new Container(
width: 44.0,
height: 44.0,
child: CachedNetworkImage(
imageUrl: doc["profUrl"],
imageBuilder: (context, imageProvider) => Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
image: imageProvider,
fit: BoxFit.cover,
),
),
),
),
);
}
return child;
}),
),
new Padding(
padding: EdgeInsets.fromLTRB(4, 4, 4, 4),
child: FutureBuilder(
future: getDownUrl(doc),
builder: (BuildContext context, snapshot) {
List<Widget> children;
if (!snapshot.hasData) {
children = [_showCircularProgress()];
} else {
children = [
Center(
child: new AspectRatio(
aspectRatio: 1 / 1,
child: Stack(
children: [
VisibilityDetector(
key: Key("unique key"),
onVisibilityChanged: (VisibilityInfo info) {
if (info.visibleFraction > .20) {
_videoPlayerController.pause();
} else {
_videoPlayerController.play();
}
},
child: CachedVideoPlayer(
_videoPlayerController,
)),
IconButton(
icon: volumeOn
? Icon(Icons.volume_up)
: Icon(Icons.volume_off),
onPressed: () {
setState(() {
_videoPlayerController.pause();
sharedPreferences.setBool(
"vidVol", !volumeOn);
});
},
),
],
),
),
)
];
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: children,
),
);
}),
),
new Row(
children: [
new IconButton(
icon: !watched
? new Icon(
Icons.remove_red_eye,
color: Colors.black26,
)
: new Icon(
Icons.remove_red_eye,
color: Colors.blueGrey[400],
),
onPressed: () {
initToggleWatched(watchList, doc["user"], name, position,
secPosition, state, year, user);
}),
Padding(
padding: EdgeInsets.fromLTRB(5, 0, 0, 0),
child: Align(
alignment: Alignment.centerLeft,
child: Text(
dateTime.day.toString() +
"/" +
dateTime.month.toString() +
"/" +
dateTime.year.toString(),
style: TextStyle(color: Colors.black26, fontSize: 12),
),
),
),
],
)
]),
);
},
);
}
Try making the widget with a controller a separate StatefullWidget instead of putting everything in one place and manage the instantiation and disposal of the controller in the initState() and dispose() methods.

How do I fix a flickering (blinking) menu screen?

I have added a GIF where you can see that when I click on favourite (heart) menu it loads smoothly and doesn't flick but when I click on side menu it flicks
I am working on an app and I am trying to resolve an issue, there is a screen whenever I click it, it flicks or blinks, it kind of refreshes. All the content it contain refresh, like if I click it I feel like I come on that screen then the items come there later on, it happens in few frictions of seconds but it is too annoying. I tried everything but still.
I tried to slow down the animation globally by using time dilation but it is still happening.
const String logo = "assets/profile/images/stadia_logo.svg";
class ProfileScreen extends StatefulWidget {
#override
_ProfileScreenState createState() => _ProfileScreenState();
}
class _ProfileScreenState extends State<ProfileScreen> {
#override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
final StorageService ref = StorageService();
final screenHeight = MediaQuery.of(context).size.height;
final screenWidth = MediaQuery.of(context).size.width;
final logoHeight = screenHeight * 0.4;
return Scaffold(
backgroundColor: Colors.white,
body: FutureBuilder(
future: ref.getProfileUrl(user.uid),
builder: (BuildContext context, AsyncSnapshot<String> url) {
if (url.connectionState == ConnectionState.waiting) {
return Loading(
size: 20,
);
}
if (url.hasData) {
return StreamBuilder<DocumentSnapshot>(
stream: DatabaseService(uid: user.uid).userData,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Loading(
size: 15,
);
}
if (snapshot.data == null) {
return Loading(
size: 15,
);
}
var userData = snapshot.data;
String _imageUrl = url.data;
if (snapshot.hasData) {
List books = userData['audio_read'];
if (books == null) {
return Loading(
size: 15,
);
//this
}
return Scaffold(
body: Stack(
children: <Widget>[
Transform.translate(
offset: Offset(screenWidth * 0.4, 10),
child: Transform.rotate(
angle: -0.1,
child: SvgPicture.asset(
logo,
height: logoHeight,
color: logoTintColor,
),
),
),
SingleChildScrollView(
child: Column(
children: <Widget>[
SizedBox(
height: 60,
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
//
createFirstNameHeader(
user, ref, userData),
Padding(
padding: const EdgeInsets.only(
right: 16.0, bottom: 16, top: 16),
child: Material(
elevation: 4,
borderRadius:
const BorderRadius.all(
Radius.circular(12)),
child: Padding(
padding: const EdgeInsets.only(
left: 16.0,
right: 16.0,
top: 16.0,
bottom: 32.0),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Row(
children: <Widget>[
Text(
"TOTAL TALES PLAYED",
style:
hoursPlayedLabelTextStyle,
),
],
),
SizedBox(
height: 4,
),
Text(
"${books.length.toString()} ${books.length > 1 ? "Tales" : "Tale"}",
style: hoursPlayedTextStyle
.copyWith(
color: Color(
0xff5E17EB)),
)
],
),
),
),
),
ContentHeadingWidget(
heading: "Continue listening"),
for (var i = books.length - 1;
i >= 0;
i--)
books.length > 0
? Slidable(
actionExtentRatio: 0.25,
actionPane:
SlidableDrawerActionPane(),
secondaryActions: <Widget>[
IconSlideAction(
caption: 'Delete',
color: Colors.red,
icon: Icons.delete,
onTap: () => {
_deletePressed(
user,
books.elementAt(
i)[
'audio_id']),
}),
],
child: LastReadBook(
audioId: books.elementAt(
i)['audio_id'],
audio_index: int.parse(
books.elementAt(i)[
'audio_index']),
audioSeek: books.elementAt(
i)['audio_seek'],
total: books.elementAt(
i)['total'],
progress: int.parse(books.elementAt(i)['audio_index']) /
books.elementAt(
i)["totalIndex"],
description:
"${books.elementAt(i)["audio_index"]} of ${books.elementAt(i)["totalIndex"]} episodes",
image: books
.elementAt(i)['image']),
)
: Loading(
size: 15,
),
],
),
),
],
),
)
],
),
);
} else {
return Loading(
size: 15,
);
}
});
} else {
return Loading(
size: 15,
);
}
}),
);
}
Padding createFirstNameHeader(
User user, StorageService ref, DocumentSnapshot userData) {
return Padding(
padding: const EdgeInsets.symmetric(
vertical: 16.0,
),
child: Row(
children: <Widget>[
createProfileImage(user, ref),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: RichText(
text: TextSpan(
children: [
TextSpan(
text: 'Hello',
style: userNameTextStyle,
),
TextSpan(text: '\n'),
TextSpan(
text: userData['firstname'], style: userNameTextStyle),
],
),
),
),
],
),
);
}
createProfileImage(User user, StorageService ref) {
return StreamBuilder(
stream: Firestore.instance
.collection("Users")
.document(user.uid)
.snapshots(),
builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
// return Center(
// child: CircularProgressIndicator(),
// );
return Loading(
size: 15,
);
}
if (snapshot.data == null) {
return Loading(
size: 15,
);
}
print(snapshot.data.data);
return GestureDetector(
onTap: () async {
if (user.uid != HomeScreen.defaultUID) {
dynamic imageFromUser = await ref.getImage();
await ref.addImageToFirebase(user.uid, imageFromUser);
} else {
createAccountDialouge(context);
}
},
child: RoundedImageWidget(
imagePath: snapshot.data["profile_image"],
icon: Icons.photo_camera,
showIcon: true),
);
});
}
createAccountDialouge(BuildContext context) {
return showDialog(
context: context,
child: CupertinoAlertDialog(
title: Text('Avid Tale Would Like to Enable Full Access'),
content: Text('Creating an account will enable access to this feature'),
actions: <Widget>[
CupertinoDialogAction(
child: Text('Cancel'),
onPressed: () {
Navigator.pop(context);
},
),
CupertinoDialogAction(
child: Text('Register'),
onPressed: () {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return RegisterScreen();
},
),
);
},
)
],
),
);
}
void _deletePressed(user, bookId) async {
DatabaseService userService = DatabaseService(uid: user.uid);
DocumentSnapshot documentSnapshot =
await Firestore.instance.collection("Users").document(user.uid).get();
var data = documentSnapshot.data["audio_read"];
data.retainWhere((element) => element["audio_id"] != bookId);
await userService.updateUserData({'audio_read': FieldValue.delete()});
await userService
.updateUserData({'audio_read': FieldValue.arrayUnion(data)});
}
}
Every time you delete an item, it triggers a new event in the Stream. As the Stream is retrieving/processing the new data it goes into this if block of code as the connectionState changes to waiting:
if (snapshot.connectionState == ConnectionState.waiting) {
return Loading(
size: 15,
);
}
Simply removing this block of code will should stop the "flickering". You may need to include other checks of data availability if necessary for your application.