I have a Provider
which changes my UI
if the value isLiked
is true
or false
. The function works fine but I noticed that every time I restart the app the UI
returns to its original state. How can I save its state so it doesn't restart when I kill the app?
here is my class:
class Selfie extends ChangeNotifier {
Selfie.fromDocument(DocumentSnapshot doc) {
selfieId = doc['selfieId'] as String;
ownerId = doc['ownerId'] as String;
displayName = doc['displayName'] as String;
photoUrl = doc['photoUrl'] as String;
mediaUrl = doc['mediaUrl'] as String;
timestamp = doc['timestamp'] as Timestamp;
likes = doc['likes'] as Map;
likesCount = doc['likesCount'] as int;
}
String selfieId;
String ownerId;
String displayName;
String photoUrl;
String mediaUrl;
Timestamp timestamp;
Map likes;
int likesCount;
bool _isLiked = false;
bool get isLiked => _isLiked;
set isLiked(bool value) {
_isLiked = value;
notifyListeners();
}
bool _showHeart = false;
bool get showHeart => _showHeart;
set showHeart(bool value) {
_showHeart = value;
notifyListeners();
}
void handleLikePost(String userId, AuthUser authUser) {
bool _isLiked = likes[userId] == true;
if (_isLiked) {
selfiesRef.doc(selfieId).update({
'likes.$userId': false,
'likesCount': FieldValue.increment(-1),
});
//removeLikeFromActivityFeed();
//likeCount -= 1;
isLiked = false;
likes[userId] = false;
selfiesRef.doc(selfieId).collection('likes').doc(userId).delete();
} else if (!_isLiked) {
selfiesRef.doc(selfieId).update({
'likes.$userId': true,
'likesCount': FieldValue.increment(1),
});
selfiesRef.doc(selfieId).collection('likes').doc(userId).set({
'displayName': authUser.displayName,
'userId': userId,
'photoUrl': authUser.photoUrl
});
//addLikeToActivityFed();
//likeCount += 1;
isLiked = true;
likes[userId] = true;
showHeart = true;
Timer(Duration(milliseconds: 500), () {
showHeart = false;
});
}
notifyListeners();
}
}
here is my UI
:
class SelfieCard extends StatelessWidget {
final Selfie selfie;
final String userId;
SelfieCard({this.selfie, this.userId});
@override
Widget build(BuildContext context) {
final AuthUser authUser =
Provider.of<UserManager>(context, listen: false).authUser;
return ChangeNotifierProvider.value(
value: selfie,
child: Consumer<Selfie>(
builder: (_, selfie, __) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15)),
clipBehavior: Clip.antiAliasWithSaveLayer,
elevation: 7,
margin: EdgeInsets.symmetric(horizontal: 16, vertical: 4),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Consumer<UserManager>(
builder: (_, userManager, __) {
bool isPostOwner = userManager.isLoggedIn
? userManager.authUser.id == selfie.ownerId
: null;
return Padding(
padding: const EdgeInsets.only(top: 0.0, bottom: 0),
child: GestureDetector(
onTap: () {},
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.grey,
backgroundImage: NetworkImage(selfie.photoUrl),
),
title: Text(
selfie.displayName,
style: TextStyle(
fontFamily: 'BebasNeue',
fontSize: 19,
color: Colors.black,
),
),
trailing: userManager.isLoggedIn && isPostOwner
? IconButton(
onPressed: () {},
icon: Icon(Icons.more_vert),
)
: Text('')),
),
);
},
),
GestureDetector(
onDoubleTap: () {},
child: Stack(
alignment: Alignment.center,
children: <Widget>[
cachedNetworkImage(selfie.mediaUrl),
selfie.showHeart
? Animator(
duration: Duration(milliseconds: 500),
tween: Tween(begin: 0.8, end: 1.4),
cycles: 0,
curve: Curves.bounceOut,
builder: (context, animatorState, chil) =>
Transform.scale(
scale: animatorState.value,
child: Icon(
Icons.favorite,
color: Colors.red,
size: 80,
),
),
)
: Text('')
],
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0, bottom: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 20.0),
child: Text(
timeago.format(selfie.timestamp.toDate(),
locale: 'en_short'),
style:
TextStyle(fontWeight: FontWeight.bold),
),
),
Expanded(
child: Container(),
),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => LikesScreen(
postId: selfie.selfieId)));
},
child: Container(
margin: EdgeInsets.only(right: 10),
child: Text(
selfie.likesCount.toString(),
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold),
),
),
),
Padding(
padding: EdgeInsets.only(
top: 40,
),
),
GestureDetector(
onTap: () {
selfie.handleLikePost(userId, authUser);
},
child: Icon(
selfie.isLiked
? Icons.favorite
: Icons.favorite_border,
color: Colors.red,
size: 25,
),
),
Padding(
padding: EdgeInsets.only(top: 40, right: 10),
),
SizedBox(
width: 20,
)
],
),
],
)),
],
),
)
],
),
);
},
));
}
}
I know I should have it on initState
but I also know that initState
can't access the context
. Do you guys have any idea how I can solve it?