Flutter: FutureBuilder一直闪烁



我在调用setState()时有一个问题。

这是问题的屏幕记录:https://cln.sh/ndL24t.

如您所见,单击小部件会使图片从加载到另一张图片之间闪烁。

这个问题是因为我有两个未来,因此是未来的建设者。第一个future返回将要显示的信息。第二个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}';
}
}

成功了。正如我在评论中提到的,我在问题发布后运行了flutter upgrade,因为发布问题后出现了一个新版本,并且还更改了代码,所以我不确定是什么解决了问题。也可能是我停止运行后又重新运行了应用程序。

最新更新