前面三篇文章:git
写了一个很简单的应用,在将这个APP的功能复杂化以前,咱们必需要选择一个合适的框架,这样才能避免代码失控,就是随着APP功能的增长,代码的结构和管理愈来愈复杂。本篇文章将如何使用InheritedWidget来管理状态。github
本篇文章所涉及的代码:json
分支:InheritedWidget数组
InheritedWidget用于在树中传递信息bash
由于InheritedWidget的实现是对象池,全部InheritedWidget的实例都在这个的对象池里,想要的时候从这个对象池里去取,因此能够在树中的任何位置都拿到InheritedWidget的单例对象,因此能够作到在树中传递信息。框架
上面说的对象池,在InheritedWidget中是一个数组,以下:async
Map<Type, InheritedElement> _inheritedWidgets;
复制代码
是一个Map,把类型Type做为key,具体实例做为value,因此0x06讲的在子节点获取InheritedWidget,你就知道为什么要传Type了ide
假设一个子节点InheritedWidget的实例,持有_inheritedWidgets
数组,这个数组的值,首先是把这个InheritedWidget父节点的_inheritedWidgets
值赋值给子节点,而后子节点在把本身的实例添加到这个数组,因此你也就能够明白0x04讲的做用域,为啥InheritedWidget的做用域是本身及本身的子节点了。post
InheritedWidget继承自ProxyWidget,ProxyWidget继承自Widget,能够单独使用,可是没有状态,为了有状态,通常和StatefulWidget搭配使用,搭配方法的示例以下: 须要有三个类:
InheritedWidget的做用域只能包括本身及本身的子节点,因此InheritedWidget在树中只能向下传递,因此在天气查询的APP中,为了让InheritedWidget的做用域是全局的,得这么作:
要覆盖Material App 的根节点。
void main(){
runApp(WeatherControllerWidget(child: MyApp()));
}
复制代码
使用 context.inheritFromWidgetOfExactType(Type targetType)
这个方法 将你想要获取的InheritedWidget的类型做为参数传进去
由于这个会常常用到,为了可读性,通常会在本身的InheritedWidget里添加of
方法,包装成以下使用:
static WeatherControllerState of(BuildContext context){
return (context.inheritFromWidgetOfExactType(_WeatherInheritedWidget) as _WeatherInheritedWidget).state;
}
复制代码
接下来咱们要写一个状态管理的类,这个类持有天气查询APP里全部的数据,以及实现数据请求的功能。代码以下:
import 'dart:convert';
import 'package:flutter/widgets.dart';
import 'package:gdg_weather/page/city/CityData.dart';
import 'package:gdg_weather/page/weather/WeatherData.dart';
import 'package:http/http.dart' as http;
//StatefulWidget 和 InheritedWidget配合使用
class WeatherControllerWidget extends StatefulWidget{
Widget child;
//这里须要传入child,这个参数,InheritedWidget初始化的时候须要用到
WeatherControllerWidget({this.child});
//这里和其余StatefulWidget同样,返回一个state
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return WeatherControllerState();
}
//这里提供了一个static方法,是为了外面好获取
static WeatherControllerState of(BuildContext context){
return (context.inheritFromWidgetOfExactType(_WeatherInheritedWidget) as _WeatherInheritedWidget).state;
}
}
//这个类是核心,用于状态管理,持有数据,而且功能都在这里实现
class WeatherControllerState extends State<WeatherControllerWidget>{
//持有的数据
List<CityData> cityList = new List<CityData>();
String curCityName;
WeatherData weather = WeatherData.empty();
//获取城市列表的方法
void getCityList() async {
final response = await http.get('https://search.heweather.net/top?group=cn&key=ebb698e9bb6844199e6fd23cbb9a77c5');
List<CityData> list = new List<CityData>();
if(response.statusCode == 200){
//解析数据
Map<String,dynamic> result = json.decode(response.body);
for(dynamic data in result['HeWeather6'][0]['basic']){
CityData cityData = CityData(data['location']);
list.add(cityData);
}
}
setState(() {
cityList = list;
});
}
//获取当前城市的实时天气
void getCityWeather() async{
final response = await http.get('https://free-api.heweather.com/s6/weather/now?location='+curCityName+'&key=ebb698e9bb6844199e6fd23cbb9a77c5');
if(response.statusCode == 200){
setState(() {
weather = WeatherData.fromJson(json.decode(response.body));
});
}else{
setState(() {
weather = WeatherData.empty();
});
}
}
//表示选择了哪一个城市
void selectCity(String city){
curCityName = city;
}
//这里返回了_WeatherInheritedWidget
@override
Widget build(BuildContext context) {
// TODO: implement build
return _WeatherInheritedWidget(
state: this,
child: widget.child,
);
}
}
//_WeatherInheritedWidget
class _WeatherInheritedWidget extends InheritedWidget{
WeatherControllerState state;
_WeatherInheritedWidget({
Key key,
@required this.state,
@required Widget child
}):super(key: key,child: child);
@override
bool updateShouldNotify(InheritedWidget oldWidget) {
// TODO: implement updateShouldNotify
return true;
}
}
复制代码
获取WeatherState的方法:
final weatherState = WeatherControllerWidget.of(context);
复制代码
具体例子以下:
class CityState extends State<CityWidget>{
CityState(){
}
@override
Widget build(BuildContext context) {
// TODO: implement build
final weatherState = WeatherControllerWidget.of(context);
weatherState.getCityList();
return ListView.builder(
itemCount: weatherState.cityList.length,
itemBuilder: (context,index){
return ListTile(
title: GestureDetector(
child: Text(weatherState.cityList[index].cityName),
onTap:(){
weatherState.selectCity(weatherState.cityList[index].cityName);
Navigator.push(
context,
MaterialPageRoute(builder: (context) => WeatherWidget())
);
},
),
);
});
}
}
复制代码