如何在 initState 上调用 Provider?
How to call Provider on initState?
我有一个 Provider
,如果值 isLiked
是 true
或 false
,它会更改我的 UI
。该功能运行良好,但我注意到每次重新启动应用程序时 UI
returns 都会恢复到其原始状态。如何保存它的状态,以便在我终止应用程序时它不会重新启动?
这是我的 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();
}
}
这是我的 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,
)
],
),
],
)),
],
),
)
],
),
);
},
));
}
}
我知道我应该在 initState
上安装它,但我也知道 initState
无法访问 context
。你们知道我该如何解决吗?
最终提供者 = Provider.of(上下文,listen:false);
问题是您的 isLiked
变量最初总是为 false。用户喜欢图片后,它正在存储,但您只是在本地临时存储它。
为了保持一致,您可以将其永久存储在本地或您的 Firestore 中。如果想存储在本地,可以使用“Shared Preferences”、“SQfLite”、“Hive”等存储。但是,如果用户删除应用程序或清除数据,效率不高,所有数据可能会丢失。
您可以像在构建方法中那样使用它...唯一的事情是您必须将 listen 设置为 false
final provider = Provider.of<T>(context, listen: false);
此处 T
是您期望的状态类型
检查 以获得进一步的解释
我有一个 Provider
,如果值 isLiked
是 true
或 false
,它会更改我的 UI
。该功能运行良好,但我注意到每次重新启动应用程序时 UI
returns 都会恢复到其原始状态。如何保存它的状态,以便在我终止应用程序时它不会重新启动?
这是我的 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();
}
}
这是我的 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,
)
],
),
],
)),
],
),
)
],
),
);
},
));
}
}
我知道我应该在 initState
上安装它,但我也知道 initState
无法访问 context
。你们知道我该如何解决吗?
最终提供者 = Provider.of(上下文,listen:false);
问题是您的 isLiked
变量最初总是为 false。用户喜欢图片后,它正在存储,但您只是在本地临时存储它。
为了保持一致,您可以将其永久存储在本地或您的 Firestore 中。如果想存储在本地,可以使用“Shared Preferences”、“SQfLite”、“Hive”等存储。但是,如果用户删除应用程序或清除数据,效率不高,所有数据可能会丢失。
您可以像在构建方法中那样使用它...唯一的事情是您必须将 listen 设置为 false
final provider = Provider.of<T>(context, listen: false);
此处 T
是您期望的状态类型
检查