【发布时间】:2021-10-20 06:40:04
【问题描述】:
拨打setState()时遇到问题。
这是该问题的屏幕记录:https://cln.sh/ndL24t。
如您所见,点击小部件会导致图片从加载到图片闪烁。
问题是因为我有两个未来,因此是未来的建设者。第一个未来返回将要显示的信息。第二个 future 根据仪表板上显示的条目的 id 返回图像。我有第一个未来的建设者得到文本未来。我将未来设置在initState() 以避免重复调用。然后我在initState() 中设置了另一个Future 变量,如下journalFuture.then(...)。我还有一个AnimatedContainer(),它在用户通过更改值并调用setState() 来点击或向上/取消时动画。我认为这是问题的原因,但我不知道如何解决。
这是我的代码:
const JournalSummary({Key? key}) : super(key: key);
@override
_JournalSummaryState createState() => _JournalSummaryState();
}
class _JournalSummaryState extends State<JournalSummary> {
final GlobalKey lottieKey = GlobalKey(debugLabel: 'Lottie Key');
late Future<List<JournalEntryData>> journalFuture;
Future? picturesFuture;
late Color _shadowColor;
double _blurRadius = 15;
void _animateDown() {
setState(() {
_shadowColor = Theme.of(context).shadowColor.withOpacity(0.40);
_blurRadius = 25;
});
}
void _animateUp() {
setState(() {
_shadowColor = Theme.of(context).shadowColor.withOpacity(0.19);
_blurRadius = 15;
});
}
@override
void initState() {
super.initState();
journalFuture = DatabaseService(uid: AuthService().getUser()!.uid)
.getJournalEntries(limit: 10);
journalFuture.then((entries) {
if (entries.isNotEmpty) {
entries
.sort((JournalEntryData firstEntry, JournalEntryData secondEntry) {
DateTime firstDate = DateTime.parse(firstEntry.date);
DateTime secondDate = DateTime.parse(secondEntry.date);
int feelingCmp = secondEntry.feeling.compareTo(firstEntry.feeling);
if (feelingCmp != 0) return feelingCmp;
return secondDate.compareTo(firstDate);
});
}
picturesFuture = StorageService(AuthService().getUser()!.uid)
.getPictures(entries[0].date);
});
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
_shadowColor = Theme.of(context).shadowColor.withOpacity(0.19);
}
@override
Widget build(BuildContext context) {
return Material(
color: Colors.transparent,
child: FutureBuilder(
future: journalFuture,
builder: (context, entryFuture) {
List<JournalEntryData> entries =
(entryFuture.data as List<JournalEntryData>?) ?? [];
if (entries.isNotEmpty) {
entries.sort(
(JournalEntryData firstEntry, JournalEntryData secondEntry) {
DateTime firstDate = DateTime.parse(firstEntry.date);
DateTime secondDate = DateTime.parse(secondEntry.date);
int feelingCmp =
secondEntry.feeling.compareTo(firstEntry.feeling);
if (feelingCmp != 0) return feelingCmp;
return secondDate.compareTo(firstDate);
});
}
return GestureDetector(
onTap: () => AppTheme.homeNavkey.currentState!.pushReplacement(
PageRouteBuilder(
transitionDuration: Duration(milliseconds: 320),
pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
return Tasks(false);
},
transitionsBuilder: (BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return Align(
child: FadeTransition(
opacity: animation,
child: child,
),
);
},
),
),
onTapDown: (_) => _animateDown(),
onTapUp: (_) => _animateUp(),
onTapCancel: () => _animateUp(),
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 25),
padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 10),
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(
color: Theme.of(context).backgroundColor,
borderRadius: BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: _shadowColor,
blurRadius: _blurRadius,
),
],
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
'assets/adobe/illustrator/icons/svg/journal_selected.svg',
width: 35,
height: 35,
),
SizedBox(width: 8),
Text(
entryFuture.data == null
? 'Journal'
: _formatedDate(entries[0].date),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: Theme.of(context)
.textTheme
.subtitle2!
.copyWith(color: Theme.of(context).primaryColor),
),
Spacer(),
(entryFuture.data == null)
? Container()
: Lottie.asset(
'assets/lottie/faces/${(entries[0].feeling == 1 ? 'sad' : (entries[0].feeling == 2 ? 'meh' : 'happy'))}.json',
key: lottieKey,
repeat: false,
width: 50,
height: 50,
),
],
),
SizedBox(height: 10),
FutureBuilder(
key: UniqueKey(),
future: picturesFuture,
initialData: [],
builder: (context, picFuture) {
return (picFuture.connectionState ==
ConnectionState.waiting ||
picturesFuture == null)
? Center(child: CircularProgressIndicator())
: SizedBox(
width:
MediaQuery.of(context).size.width - 40 - 50,
height: 160,
child: ListView(
scrollDirection: Axis.horizontal,
clipBehavior: Clip.none,
children: _buildPictures(
(picFuture.data as List<Uint8List>)),
),
);
},
),
SizedBox(height: 10),
(entryFuture.data == null)
? Container()
: Text(
entries[0].entryText,
style: Theme.of(context).textTheme.bodyText2,
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
],
),
),
),
);
},
),
);
}
List<Widget> _buildPictures(List<Uint8List> pictures) {
List<Widget> picWidgets = [];
int index = 0;
for (var pic in pictures) {
picWidgets.add(
Container(
key: UniqueKey(),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
blurRadius: 6,
color: Theme.of(context).shadowColor.withOpacity(0.52),
offset: Offset(0, 3),
)
],
),
clipBehavior: Clip.hardEdge,
margin: index == 0
? EdgeInsets.only(right: 10)
: EdgeInsets.symmetric(horizontal: 10),
child: Image.memory(
pic,
key: UniqueKey(),
height: 160,
fit: BoxFit.cover,
),
),
);
index += 1;
}
return picWidgets;
}
String _formatedDate(String date) {
DateTime dateTime = DateTime.parse(date);
Map<int, String> _monthNumToName = {
1: 'Jan',
2: 'Feb',
3: 'Mar',
4: 'Apr',
5: 'May',
6: 'Jun',
7: 'Jul',
8: 'Aug',
9: 'Sep',
10: 'Oct',
11: 'Nov',
12: 'Dec',
};
return '${_monthNumToName[dateTime.month]} ${dateTime.day}, ${dateTime.year}';
}
}
【问题讨论】:
-
在真机上试用...或连接并使用编辑器运行...问题可能出在模拟器的性能上...
-
在 PicturesFuture 的 FutureBuilder 中尝试移除 uniqueKey
-
现在可以使用了。我不确定是什么解决了这个问题,就像我同时做了几件事一样。我跑了
flutter upgrade,因为我提出这个问题后发布了一个新版本。我还稍微更改了代码,但在升级之前似乎没有修复它,所以很可能是flutter upgrade。
标签: flutter dart stateful statefulwidget