This article introduces the encapsulation of Flutter network requests and the presentation of different page states
Network request
The main use is dio library for network requests, the third library introduced. This is also possible with Flutter’s built-in HttpClient. Used to dio still can not put down. Or you can wrap HttpClient yourself if you are interested
The introduction of dio
Add to pubspec.yaml file
dio: ^3.010.
Copy the code
Introduce header file mode
import 'package:dio/dio.dart';
Copy the code
Simple packaging uses DIO
First, analyze the usage scenario. The common scenario is that after the user logs in and obtains the token, the user requests to obtain data in the request header. So let’s design along this line. Create a new base.dart file
import 'package:dio/dio.dart';
Dio initDio() {
BaseOptions _baseOptions = BaseOptions(
baseUrl: 'Set server address', connectTimeout: 15000);
Dio dio = Dio(_baseOptions);
dio.interceptors
.add(InterceptorsWrapper(onRequest: (RequestOptions options) async {
print('Go network requested setup header');
options.queryParameters['Authorization'] =
SpUtil.getString('token', defValue: ' ');
return options;
}));
return dio;
}
class Api {
static Dio dio = initDio(a);static Future<Map> requestApi(method, path, data) async {
Response result;
try {
if (method == 'get') {
result = await dio.get(path, queryParameters: data);
} else if (method == 'post') {
result = await dio.post(path, data: data);
}
print(result);
return result.data;
} on DioError catch (e) {
print(e);
if (e == null) {
return Future.error(Response(data: -1));
} else if (e.response ! = null) {
if (e.response.statusCode >= 300 && e.response.statusCode < 400) {
return Future.error(Response(data: -1));
} else {
result = e.response;
return Future.value(result.data); }}else {
return Future.error(Response(data: -1)); }}finally {
print('Network request ended'); }}}Copy the code
This initializes DIO. Specific request we can create the file again. It’s a little messy together. For example, home page requests are put together, my page requests are put together. That should make sense
class ReqHome {
Future<Map> loginInApi(username, password) {
return Api.requestApi('post'.'/login',
{"username": username, "password": password});
}
static Future<Map> getSwiperApi() {
return Api.requestApi('get'.'address'{},); }}Copy the code
Here is the call, logged in as an example
Map result = await ReqHome().logininAPI (' username ', 'password '); Sputil. putString('token', 'token');Copy the code
After obtaining the token, you need to set the token in the header
dio.interceptors
.add(InterceptorsWrapper(onRequest: (RequestOptions options) async{// Add !!!!!! here options.queryParameters['Authorization'] =
SpUtil.getString('token', defValue: ' ');
return options;
}));
Copy the code
Page different states display encapsulation
I used FutureBuilder to control the different states of the page. First create a class common_widget file, line analysis of a wave, page state divided into loading, loading completed empty data, loading completed display UI, loading failed. To demonstrate the successful loading of the image:Start by defining three properties
// final Future networkApi; // Final Function onSuccess; // Final Widget successWidget; // Successfully loaded viewCopy the code
Here is the main code:
@override
Widget build(BuildContext context) {
returnFutureBuilder<Map>(Future: widget.networkApi, Builder: (BuildContext Context, AsyncSnapshot snapshot) {// The request has endedif (snapshot.connectionState == ConnectionState.done) {
print(snapshot);
if(snapshot.haserror) {// Request failed, error displayedreturn _errorView;
} else{// Request successful, data displayedif (snapshot.data == null || snapshot.data.length == 0) {
return _emptyView;
}
widget.onSuccess();
returnwidget.successWidget; }}else{// The request is not finished, loading is displayedreturnCenter( child: CircularProgressIndicator(), ); }}); }Copy the code
Calling code:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('home'),
),
body: CommonWidget(
networkApi: ReqHome.getSwiperApi(),
successWidget: successWidget(),
onSuccess: () {},
));
}
Copy the code
Displaying the wrong UI
Add code to the common_widget file:
/// error view Widget get _errorView {return Container(
width: double.infinity,
height: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// Image.asset(
// 'assets/images/load_error_view.png',
// height: 80,
// width: 100,
// ),
Text("Loading failed. Please try again."),
RaisedButton(
color: Colors.red,
onPressed: () {
setState(() {});
},
child: Text(
'reload',
style: TextStyle(color: Colors.white),
),
)
],
),
);
}
Copy the code
The effect is as follows:
Display empty data UI
/// Widget get _emptyView {return Container(
width: double.infinity,
height: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 10),
child: Text('No data at present'() [() [(); }Copy the code
Effect:
The e view can be modified according to the UI design, the answer structure is like this.
One more things…
- List data refresh load encapsulation
- Some tool class encapsulation