Flutter网络功能插件flutter_feature_network的使用
Flutter网络功能插件flutter_feature_network的使用
flutter_feature_network
是一个为简化和增强 Flutter 应用程序中的网络操作而设计的库。该库提供了一套工具和方法来高效地管理网络请求,包括设置 Dio 客户端、日志记录、请求标识以及 SSL 安全性。
方法
获取 Dio 客户端
生成用于 HTTP 事务的 Dio 客户端。
final dioClient = FeatureNetworkRepositoryImpl().getDioClient();
// 或者
final dioClient = FlutterFeatureNetwork.getDioClient();
参数说明
参数名称 | 类型 | 是否必需 | 描述 |
---|---|---|---|
receiveTimeout |
Duration | 否 | 客户端从服务器接收数据的最大等待时间。 |
connectTimeout |
Duration | 否 | 客户端建立连接到服务器的最大允许时间。 |
sendTimeout |
Duration | 否 | 客户端发送请求数据到服务器的最大允许时间。 |
baseUrl |
String | 否 | 所有请求的基础 URL。 |
headers |
Map<String, String> | 否 | 每个请求包含的默认头信息。 |
interceptors |
List<Interceptor> | 否 | 要添加到 Dio 客户端的拦截器列表,用于修改请求/响应。 |
trustedCertificateBytes |
List<int> | 否 | 表示受信任证书的字节列表,用于 SSL 针扎。仅允许 trustedCertificateBytes 或 allowedFingerprints 中的一个。 |
allowedFingerprints |
List<String> | 否 | 允许的 SSL 证书 SHA 指纹列表,用于安全连接。仅允许 trustedCertificateBytes 或 allowedFingerprints 中的一个。 |
检查连接是否安全
检查使用证书的连接是否安全。
如果连接安全,则返回 true
,否则返回 false
。
final isSecure = FeatureNetworkRepositoryImpl().isConnectionSecure(
serverUrl: 'https://jsonplaceholder.typicode.com/',
sha: SHA.SHA_256,
allowedSHAFingerprints: [
'14f9996f9481eac7f9c005f6954c2f032d8e9cb13d4440ebed35f14bed22c43f',
],
);
// 或者
final isSecure = FlutterFeatureNetwork.isConnectionSecure(
serverUrl: 'https://jsonplaceholder.typicode.com/',
sha: SHA.SHA_256,
allowedSHAFingerprints: [
'14f9996f9481eac7f9c005f6954c2f032d8e9cb13d4440ebed35f14bed22c43f',
],
);
参数说明
参数名称 | 类型 | 是否必需 | 描述 |
---|---|---|---|
serverUrl |
String | 是 | 要检查连接的服务器 URL。 |
sha |
SHA | 是 | 用于证书指纹的哈希算法(例如 SHA_256)。 |
allowedSHAFingerprints |
List<String> | 是 | 允许的 SHA 指纹列表。 |
检查 HTTP 证书针扎
检查使用证书的连接是否安全。
FeatureNetworkRepositoryImpl().checkHttpCertificatePinning(
serverUrl: 'https://jsonplaceholder.typicode.com/',
sha: SHA.SHA_256,
allowedSHAFingerprints: [
'14f9996f9481eac7f9c005f6954c2f032d8e9cb13d4440ebed35f14bed22c43f',
],
);
// 或者
FlutterFeatureNetwork.checkHttpCertificatePinning(
serverUrl: 'https://jsonplaceholder.typicode.com/',
sha: SHA.SHA_256,
allowedSHAFingerprints: [
'14f9996f9481eac7f9c005f6954c2f032d8e9cb13d4440ebed35f14bed22c43f',
],
);
参数说明
参数名称 | 类型 | 是否必需 | 描述 |
---|---|---|---|
serverUrl |
String | 是 | 要检查连接的服务器 URL。 |
sha |
SHA | 是 | 用于证书指纹的哈希算法(例如 SHA_256)。 |
allowedSHAFingerprints |
List<String> | 是 | 允许的 SHA 指纹列表。 |
插件 FlutterFeatureNetwork
通过资源获取 HTTP 证书字节
final certificateBytes = FlutterFeatureNetwork.getCertificateBytesFromAsset(assetPath: 'asset/certificate.pem');
参数说明
参数名称 | 类型 | 是否必需 | 描述 |
---|---|---|---|
assetPath |
String | 是 | 资源路径。 |
其他
Alice
Alice 是一个用于 Flutter 的 HTTP Inspector 工具,帮助调试 HTTP 请求。它捕获并存储 HTTP 请求和响应,可以通过简单的用户界面查看。
// 设置 Alice
final alice = Alice(showNotification: true, showInspectorOnShake: true);
// 在 Material App 中使用
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
navigatorKey: alice.getNavigatorKey(),
title: 'Flutter Feature Network',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blueAccent),
useMaterial3: true,
),
home: const MainPage(),
);
}
日志拦截器
日志拦截器是一个用于在终端中调试请求和响应的拦截器。它帮助开发人员调试 HTTP。
final dio = FeatureNetworkRepositoryImpl().getDioClient(
// ...
interceptors: [
LoggerInterceptor(),
],
// ...
);
// 或者
final dio = FlutterFeatureNetwork.getDioClient(
// ...
interceptors: [
LoggerInterceptor(),
],
// ...
);
示例代码
import 'dart:io';
import 'package:example/data/repository/repository_datasource.dart';
import 'package:example/data/state/fetch_network_state.dart';
import 'package:example/domain/interceptor/dynamic_ssl_interceptor.dart';
import 'package:example/domain/interceptor/example_ssl_interceptor.dart';
import 'package:example/firebase_options.dart';
import 'package:example/presentation/main_store.dart';
import 'package:example/presentation/widget/feature_widget.dart';
import 'package:example/presentation/widget/info_bottomsheet.dart';
import 'package:example/presentation/widget/loading_dialog.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:flutter/material.dart';
import 'package:flutter_feature_network/flutter_feature_network.dart';
import 'package:get_it/get_it.dart';
import 'package:flutter_feature_platform/flutter_feature_platform.dart';
import 'package:mobx/mobx.dart';
import 'data/dto/model/feature_model.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late Alice alice;
late FirebaseRemoteConfig remoteConfig;
bool isAllFullySetup = false;
late Dio placeHolderStandardDio;
late Dio sslDio;
[@override](/user/override)
void initState() {
super.initState();
FeatureNetworkRepository networkRepository = FeatureNetworkRepositoryImpl();
GetIt.I.registerFactory<FeatureNetworkRepository>(() => networkRepository);
GetIt.I.registerFactory<FeaturePlatformRepository>(() => FeaturePlatformRepositoryImpl());
alice = Alice(showNotification: true, showInspectorOnShake: true);
GetIt.I.registerSingleton(alice);
remoteConfig = FirebaseRemoteConfig.instance;
remoteConfig.setConfigSettings(RemoteConfigSettings(
fetchTimeout: const Duration(seconds: 60),
minimumFetchInterval: const Duration(seconds: 10),
));
GetIt.I.registerSingleton(remoteConfig);
GetIt.I.get<FirebaseRemoteConfig>().fetchAndActivate();
GetIt.I.get<FirebaseRemoteConfig>().ensureInitialized();
Future.delayed(const Duration(seconds: 3), () {
setState(() {
isAllFullySetup = true;
});
});
}
[@override](/user/override)
Widget build(BuildContext context) {
return isAllFullySetup
? MaterialApp(
navigatorKey: alice.getNavigatorKey(),
title: 'Flutter Feature Network',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blueAccent),
useMaterial3: true,
),
home: const MainPage(),
)
: MaterialApp(
title: 'Flutter Feature Network - Non Alice',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepOrange),
useMaterial3: true,
),
home: const SizedBox.shrink(),
);
}
}
class MainPage extends StatefulWidget {
const MainPage({super.key});
[@override](/user/override)
State<MainPage> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
late MainStore mainStore;
bool isInitialized = false;
List<FeatureModel> features = [
FeatureModel(
title: 'Fetched Post',
desc: 'Fetched Post - OK',
key: 'FETCHED_POST_OK',
),
FeatureModel(
title: 'Fetched Post',
desc: 'Fetched Post - Correct Fingerprint',
key: 'FETCHED_POST_CORRECT_FINGERPRINT',
),
FeatureModel(
title: 'Fetched Post',
desc: 'Fetched Post - Incorrect Fingerprint',
key: 'FETCHED_POST_INCORRECT_FINGERPRINT',
),
FeatureModel(
title: 'Fetched Post',
desc: 'Fetched Post - Dynamic Fingerprint',
key: 'FETCHED_POST_DYNAMIC_FINGERPRINT',
),
FeatureModel(
title: 'Fetched Post',
desc: 'Fetched Post - Correct Certificate Byte',
key: 'FETCHED_POST_CORRECT_CERTIFICATE_BYTE',
),
FeatureModel(
title: 'Fetched Post',
desc: 'Fetched Post - Incorrect Certificate Byte',
key: 'FETCHED_POST_INCORRECT_CERTIFICATE_BYTE',
),
];
List<ReactionDisposer> reactions = [];
[@override](/user/override)
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback(
(_) {
init();
},
);
}
Future<void> init() async {
final userAgent = await GetIt.I.get<FeaturePlatformRepository>().getUserAgent();
final placeHolderStandardDio = GetIt.I.get<FeatureNetworkRepository>().getDioClient();
final placeHolderCorrectFingerprintDio = GetIt.I.get<FeatureNetworkRepository>().getDioClient(
baseUrl: 'https://jsonplaceholder.typicode.com/',
headers: {
HttpHeaders.userAgentHeader: userAgent,
},
interceptors: [
LoggerInterceptor(),
GetIt.I.get<Alice>().getDioInterceptor(),
],
allowedFingerprints: [
'14f9996f9481eac7f9c005f6954c2f032d8e9cb13d4440ebed35f14bed22c43f',
],
);
final placeHolderIncorrectFingerprintDio = GetIt.I.get<FeatureNetworkRepository>().getDioClient(
baseUrl: 'https://jsonplaceholder.typicode.com/',
headers: {
HttpHeaders.userAgentHeader: userAgent,
},
interceptors: [
GetIt.I.get<Alice>().getDioInterceptor(),
LoggerInterceptor(),
],
allowedFingerprints: [
'065e3b66390a5d3c7ce51f27342442606453b3d98e4d4e97f5b708b59d190a0a',
],
);
final placeHolderDynamicSslFingerprintDio = GetIt.I.get<FeatureNetworkRepository>().getDioClient(
baseUrl: 'https://jsonplaceholder.typicode.com/',
headers: {
HttpHeaders.userAgentHeader: userAgent,
},
interceptors: [
DynamicSslInterceptor(remoteConfig: GetIt.I.get<FirebaseRemoteConfig>()),
GetIt.I.get<Alice>().getDioInterceptor(),
LoggerInterceptor(),
],
);
final jsonPlaceholderCertByte =
await FlutterFeatureNetwork.getCertificateBytesFromAsset(assetPath: 'assets/jsonplaceholder_cert.pem');
final wikipediaCertByte =
await FlutterFeatureNetwork.getCertificateBytesFromAsset(assetPath: 'assets/wikipedia_cert.pem');
final correctCertificateByteDio = GetIt.I.get<FeatureNetworkRepository>().getDioClient(
baseUrl: 'https://jsonplaceholder.typicode.com/',
headers: {
HttpHeaders.userAgentHeader: userAgent,
},
interceptors: [
GetIt.I.get<Alice>().getDioInterceptor(),
LoggerInterceptor(),
],
trustedCertificateBytes: jsonPlaceholderCertByte,
);
final incorrectCertificateByteDio = FlutterFeatureNetwork.getDioClient(
baseUrl: 'https://jsonplaceholder.typicode.com/',
headers: {
HttpHeaders.userAgentHeader: userAgent,
},
interceptors: [
ExampleSSLInterceptor(),
GetIt.I.get<Alice>().getDioInterceptor(),
LoggerInterceptor(),
],
trustedCertificateBytes: wikipediaCertByte,
);
mainStore = MainStore(
repositoryDatasource: RepositoryDatasourceImpl(
placeHolderStandardDio: placeHolderStandardDio,
placeHolderCorrectFingerprintDio: placeHolderCorrectFingerprintDio,
placeHolderIncorrectFingerprintDio: placeHolderIncorrectFingerprintDio,
placeHolderDynamicFingerprintDio: placeHolderDynamicSslFingerprintDio,
placeHolderCorrectCertByteDio: correctCertificateByteDio,
placeHolderIncorrectCertByteDio: incorrectCertificateByteDio,
),
);
reactions = [
reaction((p0) => mainStore.fetchNetworkState, (p0) {
if (p0 is FetchNetworkLoadingState) {
showLoading();
} else if (p0 is FetchNetworkSuccessState) {
Navigator.pop(context);
showInfo(title: 'OK', desc: 'Success/Sukses');
} else if (p0 is FetchNetworkFailedState) {
Navigator.pop(context);
showInfo(title: p0.exception.title, desc: p0.exception.desc);
}
})
];
setState(() {
isInitialized = true;
});
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('NETWORK')),
body: isInitialized
? ListView.builder(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
itemCount: features.length,
itemBuilder: (_, index) {
final feature = features[index];
return GestureDetector(
onTap: () async {
switch (feature.key) {
case "FETCHED_POST_OK":
mainStore.getPostById();
break;
case "FETCHED_POST_CORRECT_FINGERPRINT":
mainStore.getPostByIdCorrectFingerprint();
break;
case "FETCHED_POST_INCORRECT_FINGERPRINT":
mainStore.getPostByIdIncorrectFingerprint();
break;
case "FETCHED_POST_DYNAMIC_FINGERPRINT":
mainStore.getPostByIdDynamicFingerprint();
break;
case "FETCHED_POST_CORRECT_CERTIFICATE_BYTE":
mainStore.getPostByIdCorrectCertByte();
break;
case "FETCHED_POST_INCORRECT_CERTIFICATE_BYTE":
mainStore.getPostByIdIncorrectCertByte();
break;
}
},
child: ItemFeatureWidget(feature: feature),
);
},
)
: const Center(
child: CircularProgressIndicator(),
),
);
}
void showLoading() {
showDialog(
context: context,
builder: (_) {
return const LoadingDialog();
},
);
}
void showInfo({required String title, required String desc}) {
showModalBottomSheet(
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(20))),
context: context,
builder: (_) {
return InfoBottomsheet(title: title, desc: desc);
},
);
}
}
更多关于Flutter网络功能插件flutter_feature_network的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter网络功能插件flutter_feature_network的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
flutter_feature_network
是一个用于简化 Flutter 应用中网络请求的插件。它提供了一些便捷的方法来处理常见的网络操作,如 GET、POST、PUT、DELETE 请求,以及文件上传和下载等。
安装
首先,你需要在 pubspec.yaml
文件中添加 flutter_feature_network
依赖:
dependencies:
flutter:
sdk: flutter
flutter_feature_network: ^1.0.0 # 请使用最新版本
然后运行 flutter pub get
来安装依赖。
基本用法
1. 初始化
在使用 flutter_feature_network
之前,通常需要初始化网络配置。你可以在应用的启动时进行初始化。
import 'package:flutter_feature_network/flutter_feature_network.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
// 初始化网络配置
NetworkConfig config = NetworkConfig(
baseUrl: "https://api.example.com",
connectTimeout: 5000,
receiveTimeout: 3000,
);
NetworkManager().init(config);
runApp(MyApp());
}
2. 发起 GET 请求
import 'package:flutter_feature_network/flutter_feature_network.dart';
Future<void> fetchData() async {
try {
Response response = await NetworkManager().get("/users");
if (response.statusCode == 200) {
print("Data: ${response.data}");
} else {
print("Failed to load data");
}
} catch (e) {
print("Error: $e");
}
}
3. 发起 POST 请求
import 'package:flutter_feature_network/flutter_feature_network.dart';
Future<void> postData() async {
try {
Response response = await NetworkManager().post(
"/users",
data: {
"name": "John Doe",
"email": "john.doe@example.com",
},
);
if (response.statusCode == 201) {
print("Data posted successfully");
} else {
print("Failed to post data");
}
} catch (e) {
print("Error: $e");
}
}
4. 发起 PUT 请求
import 'package:flutter_feature_network/flutter_feature_network.dart';
Future<void> updateData() async {
try {
Response response = await NetworkManager().put(
"/users/1",
data: {
"name": "Jane Doe",
},
);
if (response.statusCode == 200) {
print("Data updated successfully");
} else {
print("Failed to update data");
}
} catch (e) {
print("Error: $e");
}
}
5. 发起 DELETE 请求
import 'package:flutter_feature_network/flutter_feature_network.dart';
Future<void> deleteData() async {
try {
Response response = await NetworkManager().delete("/users/1");
if (response.statusCode == 204) {
print("Data deleted successfully");
} else {
print("Failed to delete data");
}
} catch (e) {
print("Error: $e");
}
}
6. 文件上传
import 'package:flutter_feature_network/flutter_feature_network.dart';
import 'package:http_parser/http_parser.dart';
Future<void> uploadFile() async {
try {
var file = await MultipartFile.fromFile(
"path/to/file.jpg",
contentType: MediaType("image", "jpg"),
);
Response response = await NetworkManager().upload(
"/upload",
files: [file],
);
if (response.statusCode == 200) {
print("File uploaded successfully");
} else {
print("Failed to upload file");
}
} catch (e) {
print("Error: $e");
}
}
7. 文件下载
import 'package:flutter_feature_network/flutter_feature_network.dart';
Future<void> downloadFile() async {
try {
String savePath = "path/to/save/file.jpg";
await NetworkManager().download("/download/file.jpg", savePath);
print("File downloaded successfully");
} catch (e) {
print("Error: $e");
}
}
高级配置
flutter_feature_network
还支持一些高级配置,如拦截器、请求头、缓存等。
1. 添加请求头
NetworkManager().addHeaders({
"Authorization": "Bearer your_token",
"Content-Type": "application/json",
});
2. 使用拦截器
NetworkManager().addInterceptor(
(RequestOptions options) {
print("Request URL: ${options.uri}");
return options;
},
(Response response) {
print("Response status: ${response.statusCode}");
return response;
},
);
3. 缓存配置
NetworkManager().enableCache(
maxAge: Duration(minutes: 10),
maxStale: Duration(days: 1),
);