#flutter
#флаттер
Вопрос:
я создал страницу друзей, где я хочу показать пользователю в правильном сегменте правильные данные. итак, я создал 3 фьючерса (запросы, подписчики и подписки)
на мой взгляд, обработка с помощью if над фьючерсами не самая лучшая, но я не знаю лучшего способа..
проблема в том, что если я переключаюсь с вкладки на вкладку, в будущих значениях будут данные из предыдущей вкладки..
есть ли какое-то четкое указание, которое я должен сделать перед переключением вкладки, или есть более элегантный способ решить эту проблему без большого содержимого if?
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:material_segmented_control/material_segmented_control.dart';
//Screens
import '../screens/friendssearch.dart';
//Services
import '../services/api_friends.dart';
//Models
import '../models/friendspending.dart';
import '../models/friendsapproved.dart';
import '../models/friendsuser.dart';
class FriendsPage extends StatefulWidget {
@override
_MyFriendsPageState createState() => _MyFriendsPageState();
}
class _MyFriendsPageState extends State<FriendsPage> {
Future<List<FriendsPending>> myFriendsPending;
Future<List<FriendsApproved>> mySubscriptions;
Future<List<FriendsUser>> mySubscribers;
int _currentSelection = 0;
void initState() {
super.initState();
myFriendsPending = FriendsApi().getFriendRequests();
mySubscriptions = FriendsApi().getSubscriptions();
mySubscribers = FriendsApi().getSubscribers();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Friends'), actions: <Widget>[
IconButton(
icon: Icon(
Icons.search,
color: Colors.white,
),
onPressed: () => {
Navigator.push(context, MaterialPageRoute(builder: (context) => FriendsSearchPage()))
},
)
]),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
MaterialSegmentedControl(
horizontalPadding: EdgeInsets.all(10),
verticalOffset: 12,
children: _children,
selectionIndex: _currentSelection,
borderColor: Colors.grey,
selectedColor: Colors.green,
unselectedColor: Colors.white,
borderRadius: 8.0,
disabledChildren: _disabledIndices,
onSegmentChosen: (index) {
setState(() {
_currentSelection = index;
});
},
),
if (_currentSelection == 0) ...[
FutureBuilder<List>(
future: myFriendsPending,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator();
} else if (snapshot.hasError) {
return Text('Error, while loading friends');
}
List friendspending = snapshot.data ?? []; <-- here are the wrong values of the tab before in the snapshot
return Expanded(
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: friendspending.length,
itemBuilder: (context, index) {
FriendsPending friend = friendspending[index];
return new ListTile(
onTap: () {},
title: new Text(friend.user),
subtitle: new Text(
friend.userdata.firstname ' ' friend.userdata.lastname),
leading: ClipOval(
child: friend.userdata.image == '' ||
friend.userdata.image == null
? CircleAvatar(
radius: 28,
backgroundColor: Colors.white,
backgroundImage:
AssetImage('assets/images/avatar.png'))
: CachedNetworkImage(
width: 56,
height: 56,
imageUrl: friend.userdata.image '?w=200amp;h=200',
placeholder: (context, url) =>
CircularProgressIndicator(),
errorWidget: (context, url, error) =>
Icon(Icons.error),
),
),
trailing: SizedBox(
height: 35,
child: FlatButton(
onPressed: () => pressAddFriendButton(friend.user),
child: Text('Accept',
style: TextStyle(color: Colors.black87)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: BorderSide(color: Colors.black87)))),
dense: false);
}));
})
] else if (_currentSelection == 1) ...[
FutureBuilder<List>(
future: mySubscriptions,
builder: (context, snapshot) {
List subscriptions = snapshot.data ?? []; <-- here are the wrong values of the tab before in the snapshot
return Expanded(
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: subscriptions.length,
itemBuilder: (context, index) {
FriendsApproved friend = subscriptions[index];
return new ListTile(
title: new Text(friend.userdata.sId),
subtitle: new Text(
friend.userdata.firstname ' ' friend.userdata.lastname),
leading: ClipOval(
child: friend.userdata.image == '' ||
friend.userdata.image == null
? CircleAvatar(
radius: 28,
backgroundColor: Colors.white,
backgroundImage:
AssetImage('assets/images/avatar.png'))
: CachedNetworkImage(
width: 56,
height: 56,
imageUrl: friend.userdata.image '?w=200amp;h=200',
placeholder: (context, url) =>
CircularProgressIndicator(),
errorWidget: (context, url, error) =>
Icon(Icons.error),
),
),
trailing: SizedBox(
height: 35,
child: FlatButton(
onPressed: () =>
pressRemoveSubscriptionButton(friend.userdata.sId),
child: Text('Remove',
style: TextStyle(color: Colors.black87)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: BorderSide(color: Colors.black87)))),
dense: false);
}));
}),
] else if (_currentSelection == 2) ...[
FutureBuilder<List>(
future: mySubscribers,
builder: (context, snapshot) {
List subscribers = snapshot.data ?? []; <-- here are the wrong values of the tab before in the snapshot
return Expanded(
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: subscribers.length,
itemBuilder: (context, index) {
FriendsUser friend = subscribers[index];
return new ListTile(
title: new Text(friend.userdata.sId),
subtitle: new Text(
friend.userdata.firstname ' ' friend.userdata.lastname),
leading: ClipOval(
child: friend.userdata.image == '' ||
friend.userdata.image == null
? CircleAvatar(
radius: 28,
backgroundColor: Colors.white,
backgroundImage:
AssetImage('assets/images/avatar.png'))
: CachedNetworkImage(
width: 56,
height: 56,
imageUrl: friend.userdata.image '?w=200amp;h=200',
placeholder: (context, url) =>
CircularProgressIndicator(),
errorWidget: (context, url, error) =>
Icon(Icons.error),
),
),
trailing: SizedBox(
height: 35,
child: FlatButton(
onPressed: () =>
pressRemoveSubscriberButton(friend.userdata.sId),
child: Text('Remove',
style: TextStyle(color: Colors.black87)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: BorderSide(color: Colors.black87)))),
dense: false);
}));
})
]
])));
}
Map<int, Widget> _children = {
0: Text(' Requests '),
1: Text(' Subscriptions '),
2: Text(' Subscribers '),
};
List<int> _disabledIndices = [];
}
Ответ №1:
Вы можете поместить a Key
в FutureBuilder
, чтобы flutter знал, что вы ссылаетесь на другой экземпляр builder . Без ключа он видит виджет того же типа и использует кэшированную версию, чтобы сократить время перестройки (поскольку считает, что она не изменилась). С ключом он будет знать, что каждый FutureBuilder
отличается.
if (_currentSelection == 0) ...[
FutureBuilder<List>(
key: ValueKey(0),
future: myFriendsPending,
...
)]
else if (_currentSelection == 1) ...[
FutureBuilder<List>(
key: ValueKey(1),
future: mySubscriptions,
...
)]
else if (_currentSelection == 2) ...[
FutureBuilder<List>(
key: ValueKey(2),
future: mySubscribers,
...
)]
Комментарии:
1. спасибо, я тоже попробую это.. тем временем я нашел решение с помощью Visibility() .. я создаю все 3 виджета и управляю 3 логическими переменными, которые контролируют видимость 3 фьючерсов