1、如何执行异步任务(async task).
这里只提最简单的一种(加关键词await,async)。假设我们有个http请求,很耗时,就需要用异步执行此任务。
dart
Future<dynamic>? getWeatherDataByCity(Map<String, dynamic> params) async {
http.Response response = await http.get(Uri.http(baseWeatherUrl, '/data/2.5/weather',
params));
print(response.statusCode);
if (response.statusCode == 200) {
print(response.body);
var json = jsonDecode(response.body);
return json;
}
}
}
注意,在dart中执行异步任务,需要使用 await 和 async 关键词。 await 用于修饰调用方法, async则在调用方法名后添加。
2、关于 Futures 的一些用法
对于await 返回的对象,我们一般用 Future包裹一下。拿到后,既可以直接使用。例如:
dart
var weatherData = await getCityWeather(typedName);
上面http接口,返回的是一个json对象,json对象返回类型 Future, 这是一个可用json对象。假设返回body的json串是:
json
{
"coord":{"lon":114.2667,"lat":30.5833},
"weather":[{"id":501,"main":"Rain","description":"moderate rain","icon":"10d"}]
}
获取json字段就很容易:
dart
var main = weatherData['weather'] ['main'];
3、在Dart 怎么用 http package.
其实 dart 已经提供了开源的 http 包给大家使用。就在这里: 【HTTP】dart 的 http 库 具体用法其实上面讲异步时已经展示过了:
dart
final String baseWeatherUrl = "api.openweathermap.org";
Map<String, dynamic> params = HashMap<String, String>();
params["lat"]= '$lat';
params["lon"]= '$lon';
params["appid"]= kApiKey;
http.Response response = await http.get(Uri.http(baseWeatherUrl, '/data/2.5/weather', params));
print(response.statusCode);
4、什么是API,怎么从APIs获取数据?
application interface,一般返回服务器的数据,数据格式有很多。所以需要我们和服务器开发人员商量好。本例,我们返回 json 格式。获取方式参考上面的方法。
5、JSONs 是什么?我们在dart中如何解析JSON?
json 是一种指定格式的数据字符串。他可以是简单地键值对。例如:
dart
{'id':222, 'name':'tom'}
也可以是嵌套很深的对象:
dart
{
"coord":{"lon":114.2667,"lat":30.5833},
"weather":[{"id":501,"main":"Rain","description":"moderate rain","icon":"10d"}]
}
dart 中,我们引入 convert 包的 jsonDecode 方法对json字符串进行解析。解析返回的对象,一般是Map<String, dynamic>
对象。获取值就可以用map对象的方式获取即可。
dart
var coord = params['coord'];
6、在页面切换时,如何用 Navigator 切换页面和传递参数。
假如我们有2个页面,当前页面: WeatherLoadingScreen , 和要跳转的页面:LocationScreen, 有个数据传递给 LocationScreen,目前有2种方法可以实现:
- 我们可以直接在 LocationScreen 构造方法里增加参数
weatherData
dart
Navigator.push(context,
MaterialPageRoute(builder: (context)=>LocationScreen(
weatherData: weatherData,
)));
类 LocationScreen
里,我们就可以用 weatherData 字段。
-
Navigator.push()
方法带上参数:arguments
. 可以参考这篇文章: navigator 带参数传递 -
返回参数 如果我们希望 LocationScreen,结束,返回参数: 可以跳转时,获取一下返回值:
dart
var cityName = await Navigator.push(context, MaterialPageRoute(
builder: (context) {
return CityScreen();
},
),
);
返回时,加上参数 cityName
:
dart
class CityScreen {
void build(BuildContext context) {
Navigator.pop(context, cityName);
}
}
在上面 cityName
就得到此返回值。
7、dart 如何处理 exceptions(使用 try/catch/throw.)
如果代码出错了,类似 java
的异常处理,dart
也会有异常处理机制。dart 的写法如下:
dart
try {
Map<String, dynamic> params = HashMap<String, String>();
params["lat"]= '$lat';
params["lon"]= '$lon';
params["appid"]= kApiKey;
http.Response response = await http.get(
Uri.http(baseWeatherUrl, '/data/2.5/weather', params));
print(response.statusCode);
if (response.statusCode == 200) {
print(response.body);
var json = jsonDecode(response.body);
return json;
}
} catch(e) {
print(e);
return null;
}
throw 一个异常也很简单:
dart
// define an exception
class ClientException implements Exception {
final String message;
/// The URL of the HTTP request or response that failed.
final Uri? uri;
ClientException(this.message, [this.uri]);
@override
String toString() {
if (uri != null) {
return 'ClientException: $message, uri=$uri';
} else {
return 'ClientException: $message';
}
}
}
void _checkResponseSuccess(Uri url, Response response) {
if (response.statusCode < 400) return;
var message = 'Request to $url failed with status ${response.statusCode}';
if (response.reasonPhrase != null) {
message = '$message: ${response.reasonPhrase}';
}
throw ClientException('$message.', url); // 抛出一个异常
}
8、StatefulWidget的生命周期方法和重载.
android的activity都是有生命周期的,onCreate(),onResume(), onDestroy()
等方法展示了 Activity的创建,暂停,销毁等。flutter 的StatefullWidget也有一些生命周期方法。 例如:
- initState() Widget的state对象创建时,会调用此方法,表示初始化
- didUpdateWidget() ,widget 的配置变化,会调用此方法。
- dispose()
9、如何使用定位获取经纬度
在android manifest.xml中需要配置定位权限。
xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="co.example.ooh">
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>
ios的plist文件也需要配置:
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access to location when open.</string>
然后咱获取定位即可:
dart
class Location {
late double _latitude;
late double _longitude;
StreamSubscription<Position>? positionStream;
Future<void> getCurrentLocation() async {
try {
LocationPermission permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
return Future.error('Location permissions are denied');
}
}
if (permission == LocationPermission.deniedForever) {
return Future.error(
'Location permissions are permanently denied, we cannot request permissions.');
}
// 获取当前经纬度
Position? position = await Geolocator.getLastKnownPosition();
positionStream = await Geolocator.getPositionStream().listen((event) {
// 暂停
positionStream?.pause();
});
if (position !=null) {
_latitude = position.latitude;
_longitude = position.longitude;
} else {
_latitude = 0;
_longitude = 0;
}
positionStream?.cancel();
} catch (e) {
print(e);
_latitude = 0;
_longitude = 0;
}
}
double getLat() {
return _latitude;
}
double getLon() {
return _longitude;
}
}
10、输入框TextField Widget获取用户输入:
dart
Container(
padding: EdgeInsets.all(20.0),
child: TextField(
style: TextStyle(
color: Colors.black,
),
decoration: kTextFieldInputDecoration,
onChanged: (value) {
cityName = value; // 获取输入框的文本
},
),
),