Provider
Provider是目前官方推荐的全局状态管理工具。
Provider的基本使用
在使用Provider时候,了解三个基本概念
ChangeNotifier:数据存在的位置,viewModel继承ChangeNotifier,处理状态变化逻辑。ChangeNotifierProvider:Provider提供创建ChangeNotifier的地方。Consumer、Selector:使用状态。
第一步:创建ChangeNotifier
我们需要一个保存状态的ChangeNotifier
- 初始化一个searchState,未进行搜索状态。
- 调用搜索事件方法
searchMapEvent,在这个方法内部处理,搜索无结果状态,搜索有结果状态等逻辑。 - 当状态发生改变时,通过Provider内部api
notifyListeners();通知Consumer更新Widget。 - 搜索的状态分别:未搜索,搜索有结果,搜索无结果
以下是ViewModel代码:
class SearchViewModel extends ChangeNotifier {
SearchState searchState = SearchStateNoSearch();
/// 高德地图搜索插件
final CRMAMapFlutterSearch _flutterSearch = AMapFlutterSearch();
SearchViewModel() {
_flutterSearch.onSearchResults().listen((date) {
...数据处理...
/// 更新状态
searchState = array.isEmpty ? SearchStateEmpty() : SearchStateSuccess<MapSearchResultEntity>(array);
notifyListeners();
});
}
/// 地图搜索
void searchMapEvent(SearchMapEvent event) async {
if (event.keyword.isEmpty) {
searchState = SearchStateNoSearch();
notifyListeners();
} else {
_flutterSearch.searchTipsWithKey(searchP);
}
}
/// 普通搜索
void searchCustomEvent(SearchCustomEvent event) async {
if (event.keyword.isEmpty) {
searchState = SearchStateNoSearch();
} else {
/// 网络请求
}
notifyListeners();
}
}
第二步:给widget树插入ChangeNotifierProvider,创建ChangeNotifier
- 因为搜索组件在整个app中不光用在地图搜索,也有普通搜索,因此将ChangeNotifierProvider放在最顶层。
- 采用
MultiProvider,方便扩展,可以添加例如:主题色,字体大小等状态变化。
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (context) => SearchViewModel(),
),
],
child: MyApp(),
);
第三步:在搜索页使用Consumer更新Widget状态
- body中,根据搜索状态不同,显示不同的widget
- 在textField输入搜索内容,修改ChangeNotifity中搜索状态
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_topSearchView(),
Expanded(
child: Consumer<SearchViewModel>(
builder: (context, searchVM, child) {
return _buildBodyBySearchState(searchVM.searchState);
},
)
),
_bottomSureView(),
],
)
_topSearchView() {
return SizedBox(
height: 40,
child: TextField(
controller: _textEditingController,),
onChanged: (keyword) {
var searchVM = context.read<SearchViewModel>();
searchVM.searchMapEvent(SearchMapEvent(keyword: keyword, city: '广州'));
},
),
);
}
/// 内容状态更新
Widget _buildBodyBySearchState(SearchState state) {
if (state is SearchStateNoSearch) return _noSearchView();
if (state is SearchStateEmpty) return _emptyResultView();
if (state is SearchStateSuccess) return _successResultView(state.searchResults);
return _noSearchView();
}