Ricardo Oscar Kanitz
Ricardo Oscar Kanitz

Reputation: 527

How to call Provider on initState?

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?

Upvotes: 0

Views: 2027

Answers (3)

iamdipanshus
iamdipanshus

Reputation: 600

you can use it the same way you've done in the build method... the only thing is you must set listen to false

final provider = Provider.of<T>(context, listen: false);

here T is the type of State you're expecting

check this for further explanation

Upvotes: 0

Preet Shah
Preet Shah

Reputation: 1037

The problem is that your isLiked variable will initially be false always. After the user likes the image, it is being stored but you're only storing it locally and temporarily.

In order to keep it consistent, you can store it permanently either locally or in your Firestore. If you want to store it locally, you can store it using "Shared Preferences", "SQfLite", "Hive", etc. However, it won't be efficient as if the user deletes the app or clears data, all of the data might get lost.

Upvotes: 0

Hamza Siddiqui
Hamza Siddiqui

Reputation: 716

final provider = Provider.of(context, listen:false);

Upvotes: 2

Related Questions