Flutter功能未知插件fadlurahmanfdev_alice的使用
Flutter功能未知插件fadlurahmanfdev_alice的使用
![](https://raw.githubusercontent.com/jhomlala/alice/master/media/logo.png)
Alice
Alice 是一个用于调试 HTTP 请求的 Flutter 工具。它捕获并存储 HTTP 请求和响应,可以通过简单的用户界面查看。该工具受到 Chuck 和 Chucker 的启发。
![](https://raw.githubusercontent.com/jhomlala/alice/master/media/1.png)
![](https://raw.githubusercontent.com/jhomlala/alice/master/media/2.png)
![](https://raw.githubusercontent.com/jhomlala/alice/master/media/3.png)
![](https://raw.githubusercontent.com/jhomlala/alice/master/media/4.png)
![](https://raw.githubusercontent.com/jhomlala/alice/master/media/5.png)
![](https://raw.githubusercontent.com/jhomlala/alice/master/media/6.png)
![](https://raw.githubusercontent.com/jhomlala/alice/master/media/7.png)
![](https://raw.githubusercontent.com/jhomlala/alice/master/media/8.png)
![](https://raw.githubusercontent.com/jhomlala/alice/master/media/9.png)
![](https://raw.githubusercontent.com/jhomlala/alice/master/media/10.png)
![](https://raw.githubusercontent.com/jhomlala/alice/master/media/11.png)
![](https://raw.githubusercontent.com/jhomlala/alice/master/media/12.png)
支持的 Dart HTTP 客户端插件:
- Dio
dart:io
包中的 HttpClienthttp/http
包中的 Http- Chopper
- 通用 HTTP 客户端
特性:
- ✔️ 详细的 HTTP 调用日志(HTTP 请求,HTTP 响应)
- ✔️ 检查器 UI 查看 HTTP 调用
- ✔️ 保存 HTTP 调用到文件
- ✔️ 统计信息
- ✔️ HTTP 调用通知
- ✔️ 支持常用的 Dart HTTP 客户端
- ✔️ 错误处理
- ✔️ 摇晃设备以打开检查器
- ✔️ HTTP 调用搜索
- ✔️ Flutter/Android 日志
安装
- 在你的
pubspec.yaml
文件中添加以下内容:
dependencies:
fadlurahmanfdev_alice: ^0.4.2
- 运行安装命令:
$ flutter packages get
- 导入库:
import 'package:fadlurahmanfdev_alice/alice.dart';
使用
Alice 配置
- 创建 Alice 实例:
Alice alice = Alice();
- 将 navigator key 添加到你的应用中:
MaterialApp(
navigatorKey: alice.getNavigatorKey(),
home: ...
)
你需要添加这个 navigator key 才能显示检查器 UI。你也可以使用自己的 navigator key:
Alice alice = Alice(showNotification: true, navigatorKey: yourNavigatorKeyHere);
如果需要延迟传递 navigatorKey,可以使用:
alice.setNavigatorKey(yourNavigatorKeyHere);
这是运行 Alice 所需的最小配置。可以在 Alice 构造函数中设置可选参数,这些参数在下面列出。如果你不希望更改任何设置,可以直接跳转到 HTTP 客户端配置。
额外设置
你可以通过在 Alice 构造函数中设置 showNotification
来显示通知。点击此通知将打开检查器:
Alice alice = Alice(..., showNotification: true);
你还可以通过在 Alice 构造函数中设置 showInspectorOnShake
来通过摇晃设备来打开检查器(默认禁用):
Alice alice = Alice(..., showInspectorOnShake: true);
如果想传递其他通知图标,可以使用 notificationIcon
参数。默认值为 @mipmap/ic_launcher
:
Alice alice = Alice(..., notificationIcon: "myNotificationIconResourceName");
如果想限制内存中保存的 HTTP 调用的最大数量,可以使用 maxCallsCount
参数:
Alice alice = Alice(..., maxCallsCount: 1000));
如果你想改变 Alice 的方向性,可以使用 directionality
参数。如果该参数为 null
,则使用应用程序的方向性:
Alice alice = Alice(..., directionality: TextDirection.ltr);
如果你想隐藏分享按钮,可以使用 showShareButton
参数:
Alice alice = Alice(..., showShareButton: false);
HTTP 客户端配置
如果你使用的是 Dio,只需添加拦截器:
Dio dio = Dio();
dio.interceptors.add(alice.getDioInterceptor());
如果你使用的是 dart:io
包中的 HttpClient:
httpClient
.getUrl(Uri.parse("https://jsonplaceholder.typicode.com/posts"))
.then((request) async {
alice.onHttpClientRequest(request);
var httpResponse = await request.close();
var responseBody = await httpResponse.transform(utf8.decoder).join();
alice.onHttpClientResponse(httpResponse, request, body: responseBody);
});
如果你使用的是 http
包中的 http:
http.get('https://jsonplaceholder.typicode.com/posts').then((response) {
alice.onHttpResponse(response);
});
如果你使用的是 Chopper,需要添加拦截器:
chopper = ChopperClient(
interceptors: [alice.getChopperInterceptor()],
);
注意!Alice 会在请求中添加特殊的 “alice_token” 头以便计算正确的 HTTP 调用 ID。
如果你有其他 HTTP 客户端,可以使用通用 HTTP 调用接口:
AliceHttpCall aliceHttpCall = AliceHttpCall(id);
alice.addHttpCall(aliceHttpCall);
手动显示检查器
如果不想使用摇晃或通知:
alice.showInspector();
保存调用
Alice 支持将日志保存到移动设备存储。为了让保存功能工作,你需要在你的 Android 应用程序清单中添加以下权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Flutter 日志
如果想在 Alice 中记录 Flutter 日志,可以使用以下方法:
alice.addLog(log);
alice.addLogs(logList);
检查器状态
检查当前检查器是否打开(打开/关闭):
alice.isInspectorOpened();
扩展
你可以使用扩展来缩短 HTTP 和 HTTP 客户端代码。这虽然是可选项,但可能会改善你的代码库。
示例
导入:
import 'package:fadlurahmanfdev_alice/core/alice_http_client_extensions.dart';
import 'package:fadlurahmanfdev_alice/core/alice_http_extensions.dart';
使用扩展:
http
.post('https://jsonplaceholder.typicode.com/posts', body: body)
.interceptWithAlice(alice, body: body);
httpClient
.postUrl(Uri.parse("https://jsonplaceholder.typicode.com/posts"))
.interceptWithAlice(alice, body: body, headers: Map());
示例代码
以下是完整的示例代码:
import 'dart:convert';
import 'dart:io';
import 'package:fadlurahmanfdev_alice/alice.dart';
import 'package:fadlurahmanfdev_alice/core/alice_http_client_extensions.dart';
import 'package:fadlurahmanfdev_alice/core/alice_http_extensions.dart';
import 'package:chopper/chopper.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart';
import 'posts_service.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
[@override](/user/override)
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late Alice _alice;
late Dio _dio;
late HttpClient _httpClient;
ChopperClient? _chopper;
late PostsService _postsService;
Color _primaryColor = Color(0xffff5e57);
Color _accentColor = Color(0xffff3f34);
Color _buttonColor = Color(0xff008000);
TextStyle _buttonTextStyle = TextStyle(color: Colors.white);
[@override](/user/override)
void initState() {
_alice = Alice(
showNotification: true,
showInspectorOnShake: true,
maxCallsCount: 1000,
);
_dio = Dio(BaseOptions(
followRedirects: false,
));
_dio.interceptors.add(_alice.getDioInterceptor());
_httpClient = HttpClient();
_chopper = ChopperClient(
interceptors: [_alice.getChopperInterceptor()],
);
_postsService = PostsService.create(_chopper);
super.initState();
}
[@override](/user/override)
Widget build(BuildContext context) {
ButtonStyle _buttonStyle = ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(_buttonColor));
return MaterialApp(
theme: ThemeData(
primaryColor: _primaryColor,
colorScheme: ColorScheme.light(secondary: _accentColor),
),
navigatorKey: _alice.getNavigatorKey(),
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Alice HTTP Inspector - Example'),
),
body: Container(
padding: EdgeInsets.all(16),
child: ListView(
children: [
const SizedBox(height: 8),
_getTextWidget(
'欢迎来到 Alice Http Inspector 示例。请点击下面的按钮生成示例数据。'),
ElevatedButton(
child: Text(
'运行 Dio HTTP 请求',
style: _buttonTextStyle,
),
onPressed: _runDioRequests,
style: _buttonStyle,
),
const SizedBox(height: 8),
ElevatedButton(
child: Text(
'运行 http/http HTTP 请求',
style: _buttonTextStyle,
),
onPressed: _runHttpHttpRequests,
style: _buttonStyle,
),
const SizedBox(height: 8),
ElevatedButton(
child: Text(
'运行 HttpClient 请求',
style: _buttonTextStyle,
),
onPressed: _runHttpHttpClientRequests,
style: _buttonStyle,
),
const SizedBox(height: 8),
ElevatedButton(
child: Text(
'运行 Chopper HTTP 请求',
style: _buttonTextStyle,
),
onPressed: _runChopperHttpRequests,
style: _buttonStyle,
),
const SizedBox(height: 8),
ElevatedButton(
child: Text(
'日志示例数据',
style: _buttonTextStyle,
),
onPressed: _logExampleData,
style: _buttonStyle,
),
const SizedBox(height: 24),
_getTextWidget(
'点击上面的按钮后,你应该会收到通知。点击通知以显示检查器。你也可以摇晃你的设备或点击下面的按钮。'),
ElevatedButton(
child: Text(
'运行 HTTP 检查器',
style: _buttonTextStyle,
),
onPressed: _runHttpInspector,
style: _buttonStyle,
)
],
),
),
),
);
}
Widget _getTextWidget(String text) {
return Text(
text,
style: TextStyle(fontSize: 14),
textAlign: TextAlign.center,
);
}
void _logExampleData() {
final List<AliceLog> logs = [];
logs.add(
AliceLog(
level: DiagnosticLevel.info,
timestamp: DateTime.now(),
message: 'Info log',
),
);
logs.add(
AliceLog(
level: DiagnosticLevel.debug,
timestamp: DateTime.now(),
message: 'Debug log',
),
);
logs.add(
AliceLog(
level: DiagnosticLevel.warning,
timestamp: DateTime.now(),
message: 'Warning log',
),
);
final notNumber = 'afs';
try {
int.parse(notNumber);
} catch (e, stacktrace) {
logs.add(
AliceLog(
level: DiagnosticLevel.error,
timestamp: DateTime.now(),
message: 'Error log',
error: e,
stackTrace: stacktrace,
),
);
}
_alice.addLogs(logs);
}
void _runChopperHttpRequests() async {
String body = jsonEncode(
<String, dynamic>{'title': 'foo', 'body': 'bar', 'userId': '1'});
_postsService.getPost('1');
_postsService.postPost(body);
_postsService.putPost('1', body);
_postsService.putPost('1231923', body);
_postsService.putPost('1', null);
_postsService.postPost(null);
_postsService.getPost('123456');
}
void _runDioRequests() async {
Map<String, dynamic> body = <String, dynamic>{
'title': 'foo',
'body': 'bar',
'userId': '1'
};
_dio.get<void>(
'https://httpbin.org/redirect-to?url=https%3A%2F%2Fhttpbin.org');
_dio.delete<void>('https://httpbin.org/status/500');
_dio.delete<void>('https://httpbin.org/status/400');
_dio.delete<void>('https://httpbin.org/status/300');
_dio.delete<void>('https://httpbin.org/status/200');
_dio.delete<void>('https://httpbin.org/status/100');
_dio.post<void>('https://jsonplaceholder.typicode.com/posts', data: body);
_dio.get<void>('https://jsonplaceholder.typicode.com/posts',
queryParameters: <String, dynamic>{'test': 1});
_dio.put<void>('https://jsonplaceholder.typicode.com/posts/1', data: body);
_dio.put<void>('https://jsonplaceholder.typicode.com/posts/1', data: body);
_dio.delete<void>('https://jsonplaceholder.typicode.com/posts/1');
_dio.get<void>('http://jsonplaceholder.typicode.com/test/test');
_dio.get<void>('https://jsonplaceholder.typicode.com/photos');
_dio.get<void>(
'https://icons.iconarchive.com/icons/paomedia/small-n-flat/256/sign-info-icon.png');
_dio.get<void>(
'https://images.unsplash.com/photo-1542736705-53f0131d1e98?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&w=1000&q=80');
_dio.get<void>(
'https://findicons.com/files/icons/1322/world_of_aqua_5/128/bluetooth.png');
_dio.get<void>(
'https://upload.wikimedia.org/wikipedia/commons/4/4e/Pleiades_large.jpg');
_dio.get<void>('http://techslides.com/demos/sample-videos/small.mp4');
_dio.get<void>('https://www.cse.wustl.edu/~jain/cis677-97/ftp/e_3dlc2.pdf');
final directory = await getApplicationDocumentsDirectory();
File file = File('${directory.path}/test.txt');
file.create();
file.writeAsStringSync('123456789');
String fileName = file.path.split('/').last;
FormData formData = FormData.fromMap(<String, dynamic>{
'file': await MultipartFile.fromFile(file.path, filename: fileName),
});
_dio.post<void>('https://jsonplaceholder.typicode.com/photos',
data: formData);
_dio.get<void>('http://dummy.restapiexample.com/api/v1/employees');
}
void _runHttpHttpRequests() async {
Map<String, String> body = <String, String>{
'title': 'foo',
'body': 'bar',
'userId': '1'
};
http
.post(Uri.tryParse('https://jsonplaceholder.typicode.com/posts')!,
body: body)
.interceptWithAlice(_alice, body: body);
http
.get(Uri.tryParse('https://jsonplaceholder.typicode.com/posts')!)
.interceptWithAlice(_alice);
http
.put(Uri.tryParse('https://jsonplaceholder.typicode.com/posts/1')!,
body: body)
.interceptWithAlice(_alice, body: body);
http
.patch(Uri.tryParse('https://jsonplaceholder.typicode.com/posts/1')!,
body: body)
.interceptWithAlice(_alice, body: body);
http
.delete(Uri.tryParse('https://jsonplaceholder.typicode.com/posts/1')!)
.interceptWithAlice(_alice, body: body);
http
.get(Uri.tryParse('https://jsonplaceholder.typicode.com/test/test')!)
.interceptWithAlice(_alice);
http
.post(Uri.tryParse('https://jsonplaceholder.typicode.com/posts')!,
body: body)
.then((response) {
_alice.onHttpResponse(response, body: body);
});
http
.get(Uri.tryParse('https://jsonplaceholder.typicode.com/posts')!)
.then((response) {
_alice.onHttpResponse(response);
});
http
.put(Uri.tryParse('https://jsonplaceholder.typicode.com/posts/1')!,
body: body)
.then((response) {
_alice.onHttpResponse(response, body: body);
});
http
.patch(Uri.tryParse('https://jsonplaceholder.typicode.com/posts/1')!,
body: body)
.then((response) {
_alice.onHttpResponse(response, body: body);
});
http
.delete(Uri.tryParse('https://jsonplaceholder.typicode.com/posts/1')!)
.then((response) {
_alice.onHttpResponse(response);
});
http
.get(Uri.tryParse('https://jsonplaceholder.typicode.com/test/test')!)
.then((response) {
_alice.onHttpResponse(response);
});
http
.post(
Uri.tryParse(
'https://jsonplaceholder.typicode.com/posts?key1=value1')!,
body: body)
.interceptWithAlice(_alice, body: body);
http
.post(
Uri.tryParse(
'https://jsonplaceholder.typicode.com/posts?key1=value1&key2=value2&key3=value3')!,
body: body)
.interceptWithAlice(_alice, body: body);
http
.get(Uri.tryParse(
'https://jsonplaceholder.typicode.com/test/test?key1=value1&key2=value2&key3=value3')!)
.then((response) {
_alice.onHttpResponse(response);
});
}
void _runHttpHttpClientRequests() {
Map<String, dynamic> body = <String, dynamic>{
'title': 'foo',
'body': 'bar',
'userId': '1'
};
_httpClient
.getUrl(Uri.parse('https://jsonplaceholder.typicode.com/posts'))
.interceptWithAlice(_alice);
_httpClient
.postUrl(Uri.parse('https://jsonplaceholder.typicode.com/posts'))
.interceptWithAlice(_alice, body: body, headers: <String, dynamic>{});
_httpClient
.putUrl(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'))
.interceptWithAlice(_alice, body: body);
_httpClient
.getUrl(Uri.parse('https://jsonplaceholder.typicode.com/test/test/'))
.interceptWithAlice(_alice);
_httpClient
.postUrl(Uri.parse('https://jsonplaceholder.typicode.com/posts'))
.then((request) async {
_alice.onHttpClientRequest(request, body: body);
request.write(body);
var httpResponse = await request.close();
var responseBody = await utf8.decoder.bind(httpResponse).join();
_alice.onHttpClientResponse(httpResponse, request, body: responseBody);
});
_httpClient
.putUrl(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'))
.then((request) async {
_alice.onHttpClientRequest(request, body: body);
request.write(body);
var httpResponse = await request.close();
var responseBody = await utf8.decoder.bind(httpResponse).join();
_alice.onHttpClientResponse(httpResponse, request, body: responseBody);
});
_httpClient
.patchUrl(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'))
.then((request) async {
_alice.onHttpClientRequest(request, body: body);
request.write(body);
var httpResponse = await request.close();
var responseBody = await utf8.decoder.bind(httpResponse).join();
_alice.onHttpClientResponse(httpResponse, request, body: responseBody);
});
_httpClient
.deleteUrl(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'))
.then((request) async {
_alice.onHttpClientRequest(request);
var httpResponse = await request.close();
var responseBody = await utf8.decoder.bind(httpResponse).join();
_alice.onHttpClientResponse(httpResponse, request, body: responseBody);
});
_httpClient
.getUrl(Uri.parse('https://jsonplaceholder.typicode.com/test/test/'))
.then((request) async {
_alice.onHttpClientRequest(request);
var httpResponse = await request.close();
var responseBody = await utf8.decoder.bind(httpResponse).join();
_alice.onHttpClientResponse(httpResponse, request, body: responseBody);
});
}
void _runHttpInspector() {
_alice.showInspector();
}
}
更多关于Flutter功能未知插件fadlurahmanfdev_alice的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter功能未知插件fadlurahmanfdev_alice的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
fadlurahmanfdev_alice
是一个 Flutter 插件,主要用于调试和监控网络请求。它类似于其他网络调试工具(如 Chucker
或 Flipper
),通过展示应用中的 HTTP 请求和响应,帮助开发者调试和分析网络交互。
以下是关于 fadlurahmanfdev_alice
的详细使用方法和功能说明:
功能特点
- HTTP 请求监控:捕获应用中所有的 HTTP 请求和响应,包括 URL、请求方法、请求头、请求体、响应状态码、响应头和响应体。
- UI 展示:通过一个可交互的界面展示捕获的网络请求,方便查看详细信息。
- 调试模式:在调试阶段使用,帮助开发者快速定位问题。
- 支持多种请求库:可以与
Dio
、http
等常见的 Flutter 网络请求库集成。
安装
在 pubspec.yaml
中添加依赖:
dependencies:
fadlurahmanfdev_alice: ^1.0.0
运行 flutter pub get
安装插件。
基本用法
-
初始化 Alice
import 'package:fadlurahmanfdev_alice/fadlurahmanfdev_alice.dart'; final Alice alice = Alice();
-
集成到网络请求库
-
集成
Dio
import 'package:dio/dio.dart'; import 'package:fadlurahmanfdev_alice/dio/alice_dio_interceptor.dart'; final dio = Dio(); dio.interceptors.add(AliceDioInterceptor(alice));
-
集成
http
import 'package:http/http.dart' as http; import 'package:fadlurahmanfdev_alice/http/alice_http_client.dart'; final client = AliceHttpClient(alice, http.Client());
-
-
打开监控界面 在需要查看网络请求时,调用以下方法打开监控界面:
alice.showInspector();
-
示例代码
import 'package:flutter/material.dart'; import 'package:dio/dio.dart'; import 'package:fadlurahmanfdev_alice/fadlurahmanfdev_alice.dart'; import 'package:fadlurahmanfdev_alice/dio/alice_dio_interceptor.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { final Alice alice = Alice(); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('Alice Example'), ), body: Center( child: ElevatedButton( onPressed: () async { final dio = Dio(); dio.interceptors.add(AliceDioInterceptor(alice)); try { final response = await dio.get('https://jsonplaceholder.typicode.com/posts'); print(response.data); } catch (e) { print(e); } }, child: Text('Send Request'), ), ), floatingActionButton: FloatingActionButton( onPressed: () { alice.showInspector(); }, child: Icon(Icons.network_check), ), ), ); } }