Flutter网络连接管理插件connection_manager的使用
Flutter网络连接管理插件connection_manager的使用
标题
Flutter网络连接管理插件connection_manager的使用
内容
This package provides a simple implementation of a Connection Manager to do API request to a Server (REST or GraphQL). Furthermore, it provides an ApiCallBuilder widget to easily integrate API calls in the widget tree and a PaginatedApiCallBuilder widget to easily integrate paginated API calls in the widget tree.
Features
- ConnectionManager: A class to make API requests, created setting a baseurl and headers to use for all the API calls.
- PostApiResponse: A class to manage responses from the
ConnectionManager
, decoded by the provided class. - Decodable: A class to implement to let this package decode custom classes from a Map.
- ApiCallBuilder: A widget to easily integrate API calls in the widget tree.
- PaginatedApiCallBuilder: A widget to easily integrate paginated API calls in the widget tree.
Usage
Check the usage paragraph according to your needs.
Setting up
Before using the ConnectionManager
, it must be initialized providing a baseUrl and headers. It can be useful to save a single instance of the ConnectionManager
to be used all through the app, for example as a singleton.
To initialize the class:
ConnectionManager(
baseUrl: "https://my-base-url.com",
constantHeaders: {
"Content-Type": "application/json",
},
decodeErrorFromMap: CustomError.fromMapError, // Optional, to let the package try to automatically decode errors from server. It's a method passed as a tear off
mapStatusCodeFromResponse: (map) => map?["code"], // Optional, you can use this method to map a code from body and use it to override the http status code.
onTokenExpiredRuleOverride: (response) {
if (response.statusCode == 500 && response.body.contains("missing auth")) {
return true;
}
return false;
}, /// Optional, this method can be used in combination with `onTokenExpired` to define a custom rule to trigger the `onTokenExpired` method. By default, `onTokenExpired` is fired when the http response has a 401 status code. Eventually, this rule can be expanded thanks to this method.
onTokenExpired: () async {
return await refreshToken(); // refreshToken is not a method of this package
}, // A function fired when the http client gives a 401 response after an API call. It is used to refresh the auth token, if set, and after returning the new token the [ConnectionManager] will attempt the API call once again.
onResponseReceived: (Response response) {
print(response.body);
}, // A function fired, if not _null_, when the `doApiRequest` method receives a response from the BE. This can be useful to manage broadly a `Response` the same way for every api call.
returnCatchedErrorMessage: true, // Specify if the error message coming from the try-catch block in `doApiRequest` should be returned in the response (i.e. decoding errors). Default to _true_.
duration: const Duration(seconds: 1), // Specify the timeout for all the API calls done with this [ConnectionManager]. Defaults to 1 minute.
persistCookies: false, // If _true_, creates a persistent instance of a cookie manager to be used for all the API calls done with this [ConnectionManager]. Defaults to _false_
client: Client(), // If set, overrides the default http client for API calls
)
In the example above, CustomError
is a local class that implements Decodable
in this package and its fromMapError
method. See Decodable
documentation for further details.
You can store a single instance of the ConnectionManager
as a Provider or as a singleton. Check this example:
class NetworkProvider {
final String baseUrl;
// Connection Manager definition
final _connectionManager = ConnectionManager<CustomError>(
baseUrl: baseUrl,
constantHeaders: {"Content-Type": "application/json"},
decodeErrorFromMap: CustomError.fromMapError,
onTokenExpired: () async {
return await refreshToken(); // refreshToken() is not a method of this package
},
onResponseReceived: (Response response) {
print(response.body);
},
returnCatchedErrorMessage: true,
);
// Connection Manager getter
ConnectionManager<CustomError> get connectionManager => _connectionManager;
}
// Use the provider
class MyApp extends StatelessWidget {
@override build(BuildContext context) {
return Provider(
create: (context) => NetworkProvider(
baseUrl: "https://test.com/api",
),
child: Builder(
builder: (context) {
var networkProvider = context.read<NetworkProvider>();
return Text(networkProvider.baseUrl);
}
),
);
}
}
Modify ConnectionManager
Other than passing constant headers to the ConnectionManager
constructor, it is possible to add/remove extra headers to be used for all the API calls by calling one of the following methods on the created instance.
context.read<NetworkProvider>().connectionManager.setSharedHeaders({
"Authorization" : "token"
});
context.read<NetworkProvider>().connectionManager.setAuthHeader("Bearer token");
context.read<NetworkProvider>().connectionManager.removeAuthHeader();
Furthermore, it is possibile to edit the baseurl
context.read<NetworkProvider>().connectionManager.changeBaseUrl("https://test.com/api/v1");
Make an api request
To make an API request simply call the method doAPIRequest
on the ConnectionManager
, passing all the required parameters, and eventually other headers or a body.
The method is asyncronous, and it will return a PostApiResponse
as a Future
, containing the decoded content, the http status code and eventually an error message.
Other than specifying the request type (get, post…), it is possible to specify the body type: json, formdata, graphQL… To do so, use the bodyType
parameter (defaults to json type). Note: When passing a json body, it’s mandatory to json encode the Map, as follows.
var response = await context.read<NetworkProvider>().connectionManager.doApiRequest(
requestType: ApiRequestType.post,
endpoint: "/test-endpoint",
body: jsonEncode({
"test": "test"
}),
);
When using a formData body, it’s mandatory to pass it as a Map<String,dynamic>
. To pass a file, use the FileData
class provided by this library to create a file and add it as a vaue of the Map. It’s left to the package to manage it correctly.
Whenn using a graphQL body, it’s mandatory to pass it as a [String]. Parameters must be passed as values in the string itself. The [ApiRequestType] should be get for queries or anything else for mutations.
更多关于Flutter网络连接管理插件connection_manager的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter网络连接管理插件connection_manager的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用Flutter中的connection_manager
插件进行网络连接管理的代码示例。connection_manager
插件允许你检测设备的网络连接状态,并在连接状态发生变化时执行相应的操作。
首先,你需要在你的pubspec.yaml
文件中添加connection_manager
依赖:
dependencies:
flutter:
sdk: flutter
connection_manager: ^0.6.0 # 请检查最新版本号
然后运行flutter pub get
来安装依赖。
接下来是一个完整的Flutter应用示例,它展示了如何使用connection_manager
插件来监听网络连接状态的变化:
import 'package:flutter/material.dart';
import 'package:connection_manager/connection_manager.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
ConnectionManager _connectionManager = ConnectionManager();
String _connectionStatus = "Checking...";
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
_checkConnectionStatus();
_connectionManager.status.listen((status) {
setState(() {
_updateConnectionStatus(status);
});
});
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
_connectionManager.dispose();
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
_checkConnectionStatus();
}
}
Future<void> _checkConnectionStatus() async {
var status = await _connectionManager.checkConnection();
_updateConnectionStatus(status);
}
void _updateConnectionStatus(ConnectionStatus status) {
setState(() {
switch (status) {
case ConnectionStatus.WIFI:
_connectionStatus = "Connected to Wi-Fi";
break;
case ConnectionStatus.MOBILE:
_connectionStatus = "Connected to Mobile Data";
break;
case ConnectionStatus.NONE:
_connectionStatus = "No Internet Connection";
break;
}
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Connection Manager Example'),
),
body: Center(
child: Text(
_connectionStatus,
style: TextStyle(fontSize: 24),
),
),
),
);
}
}
代码说明:
- 依赖添加:在
pubspec.yaml
中添加connection_manager
依赖。 - 状态管理:使用
StatefulWidget
和State
来管理应用的状态。 - 初始化:在
initState
方法中初始化ConnectionManager
实例,并添加监听器来监听连接状态的变化。 - 连接状态检查:定义一个
_checkConnectionStatus
方法,用于检查当前的连接状态。 - 更新UI:根据连接状态更新UI文本。
- 生命周期管理:在
didChangeAppLifecycleState
方法中,当应用从后台切换到前台时,重新检查连接状态。 - 资源释放:在
dispose
方法中释放资源,避免内存泄漏。
这个示例展示了如何使用connection_manager
插件来检测设备的网络连接状态,并在状态变化时更新UI。你可以根据实际需求进一步扩展这个示例。