#flutter #dart #stateful #statefulwidget
Вопрос:
У меня проблема при звонке setState()
.
Вот экранная запись проблемы: https://cln.sh/ndL24t.
Как вы можете видеть, нажатие на виджет приводит к тому, что картинка мигает от загрузки к картинке.
Проблема вызвана тем, что у меня есть два будущего и, следовательно, для будущих строителей. Первое будущее возвращает информацию, которая будет отображаться. Второе будущее возвращает изображения на основе идентификатора записи, отображаемой на панели мониторинга. У меня есть первый строитель будущего, который получит текст будущего. Я настроил будущее на initState()
то, чтобы избежать повторных звонков. Затем у меня есть еще Future
одна переменная, которую я задаю initState()
следующим образом 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}';
}
}
Комментарии:
1. попробуйте это на реальном телефоне… или подключитесь и запустите с редактором.. проблема может быть в производительности эмулятора..
2. Попробуйте удалить uniqueKey в FutureBuilder из Picturefuture
3. Теперь это работает. Я не уверен, что исправило проблему точно так же, как я сделал несколько вещей одновременно. Я бежал
flutter upgrade
с тех пор, как была выпущена новая версия, с тех пор как я задал этот вопрос. Я также немного изменил код, но, похоже, это не исправило его до обновления, так что, скорееflutter upgrade
всего, это так .
Ответ №1:
Это сработало. Как упоминалось в моем комментарии, я побежал flutter upgrade
после публикации вопроса, потому что после публикации вопроса вышла новая версия, а также немного изменил код, поэтому я не уверен, что исправило проблему. Это также могло быть связано с тем, что я перестал работать, а затем снова запустил приложение.