假设我有这样的东西:
return FutureBuilder(
future: _loadingDeals,
builder: (BuildContext context, AsyncSnapshot snapshot) {
return RefreshIndicator(
onRefresh: _handleRefresh,
...
)
}
)
在_handleRefresh
方法中,我要以编程方式触发FutureBuilder的重新运行。
有这样的东西吗?
用例:
当用户拉下refreshIndicator
时,_handleRefresh
只会使FutureBuilder
重新运行。
修改:
完整的代码段首尾相连,没有刷新的部分。我已改用StreamBuilder
,refreshIndicator
部分将如何适合所有部分?
class DealList extends StatefulWidget {
@override
State<StatefulWidget> createState() => new _DealList();
}
class _DealList extends State<DealList> with AutomaticKeepAliveClientMixin {
// prevents refreshing of tab when switch to
// Why? https://stackoverflow.com/q/51224420/1757321
bool get wantKeepAlive => true;
final RestDatasource api = new RestDatasource();
String token;
StreamController _dealsController;
@override
void initState() {
super.initState();
_dealsController = new StreamController();
_loadingDeals();
}
_loadingDeals() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
this.token = prefs.getString('token');
final res =
this.api.checkInterests(this.token).then((interestResponse) async {
_dealsController.add(interestResponse);
return interestResponse;
});
return res;
}
_handleRefresh(data) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
final token = prefs.getString('token');
await this.api.checkInterests(token).then((interestResponse) {
_dealsController.add(interestResponse);
});
return null;
}
@override
Widget build(BuildContext context) {
super.build(context); // <-- this is with the wantKeepAlive thing
return StreamBuilder(
stream: _dealsController.stream,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasError) {
...
}
if (snapshot.connectionState != ConnectionState.done) {
return Center(
child: CircularProgressIndicator(),
);
}
if (!snapshot.hasData &&
snapshot.connectionState == ConnectionState.done) {
return Text('No deals');
}
if (snapshot.hasData) {
return ListView.builder(
physics: const AlwaysScrollableScrollPhysics(),
itemCount: snapshot.data['deals'].length,
itemBuilder: (context, index) {
final Map deal = snapshot.data['deals'][index];
return ListTile(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DealsDetailPage(
dealDetail: deal,
),
),
);
},
title: Text(deal['name']),
subtitle: Text(deal['expires']),
);
},
),
}
},
);
}
}
答案 0 :(得分:4)
为什么不使用StreamBuilder和Stream代替FutureBuilder?
类似的东西...
/^[a-z$_][$\w]*(\.[a-z$_][$\w]*)*$/i
我使用StreamBuilder check it out
用Flutter主要示例创建了一个Gist。答案 1 :(得分:0)
使用StreamBuilder是一种解决方案,但是,以编程方式触发FutureBuilder,只需调用setState,它将重新构建Widget。
class MedicalConditionSelectionReactor: Reactor {
// represent user actions
enum Action {
case loadConditions
case addNewCondition
case removeCondition
case toggleCondition(index: Int)
case save
}
// represent state changes
enum Mutation {
case loadedMedicalConditions([MedicalConditionSelectionSectionItem])
case reloadList
}
// represents the current view state
struct State {
var sections: [MedicalConditionSelectionSection] = [MedicalConditionSelectionSection(items: [])]
}
let initialState: State = State()
func mutate(action: Action) -> Observable<Mutation> {
switch action {
case .loadConditions:
let medicalConditions = OptionsModelDBProvider<RealmMedicalConditionModel>().fetch()
let conditions = medicalConditions.toArray().map { item -> MedicalConditionSelectionSectionItem in
// let isSelected = arrayOfMedicalConditionID.contains("\(item.ID)")
let medicalCell = MedicineCellReactor(id: "\(item.ID)", title: item.name, isSelected: false)
return MedicalConditionSelectionSectionItem.medicalCondition(medicalCell)
}
return Observable.of(Mutation.loadedMedicalConditions(conditions))
case let .toggleCondition(indexOfCell):
let state = currentState.sections[0].items[indexOfCell]
switch state {
case let .medicalCondition(reactor):
// TODO:- How to toggle the isSelected bool property of MedicineCellReactor.State. Since this is immutable.
// reactor.currentState.isSelected = false
break
default: break
}
return Observable.of(Mutation.reloadList)
default:
return Observable.of(Mutation.reloadList)
}
}
func reduce(state: State, mutation: Mutation) -> State {
var state = state
switch mutation {
case let .loadedMedicalConditions(conditions):
state.sections[0].items = conditions
default:
break
}
return state
}
}
答案 2 :(得分:0)
我更喜欢 FutureBuilder 而不是 StreamBuilder,因为我在我的项目中使用 Firestore 并且您按读取收费,所以我的解决方案是这样的
_future??= getMyFuture();
shouldReload(){
setState(()=>_future = null)
}
FutureBuilder(
future: _future,
builder: (context, snapshot){
return Container();
},
)
以及任何需要您获取新数据的用户活动,只需调用 shouldReload()