介绍
由于业务使用的通信协议为 Protocol Buffer
,所以文章主要以如何通过 Protocol Buffer
发起网络请求为主。
安装 protoc
需要借助 protocol buffer
编译工具,将 .proto
文件编译为 .dart
文件
目录结构
├─protocols
│ ├─lib
│ │ ├─api
│ │ │ └─api.dart
│ │ ├─gen
│ │ ├─pb
│ │ │ └─web.ext.proto
│ │ └─protocols.dart
│ └─pubspec.yaml
在项目根目录下创建 protocols
,添加 pubspec.yaml
,使其成为一个模块。在 pb
目录中存放 .proto
文件,生成的 .dart
文件放在 gen
文件夹中。
pubspec.yaml
文件内容:
使用了 protobuf
、protoc_plugin
和 http
依赖。
name: protocols
description: A new Flutter package project.
version: 0.0.1
publish_to: none
environment:
sdk: ">=3.3.0 <4.0.0"
flutter: ">=3.19.0"
dependencies:
flutter:
sdk: flutter
protobuf: ^3.1.0
http: ^1.2.2
dev_dependencies:
flutter_test:
sdk: flutter
protoc_plugin: 21.1.2
flutter:
在终端中打开 protocols
目录并执行 flutter pub get
来安装依赖。
web.ext.proto
内容:
syntax = "proto3";
service WebService {
rpc GetResponse(RequestMessage) returns (ResponseMessage);
}
message RequestMessage {
string name = 1;
}
message ResponseMessage {
string message = 1;
}
执行编译命令
protoc --dart_out=D:\my_flutter_web\protocols\lib\gen --proto_path=D:\my_flutter_web\protocols\lib\pb web.ext.proto
将会在 protocols\lib\gen
目录下生成 web.ext.pb.dart、web.ext.pbenum.dart、web.ext.pbjson.dart、web.ext.pbserver.dart
文件。
主要使用 web.ext.pb.dart
和 web.ext.pbenum.dart
文件。
实现 request.dart
分析 web.ext.pb.dart
文件,可以看出需要创建一个 class
继承抽象类 RpcClient
来实现 invoke
方法。
web.ext.pb.dart
文件部分内容:
...
class WebServiceApi {
$pb.RpcClient _client;
WebServiceApi(this._client);
$async.Future<ResponseMessage> getResponse($pb.ClientContext? ctx, RequestMessage request) =>
_client.invoke<ResponseMessage>(ctx, 'WebService', 'GetResponse', request, ResponseMessage())
;
}
...
request.dart
:
import 'package:http/http.dart' as http;
import 'package:protobuf/protobuf.dart';
class Request extends RpcClient {
final String apiUrl;
Request({required this.apiUrl});
Future<T> invoke<T extends GeneratedMessage>(
ClientContext? ctx,
String serviceName,
String methodName,
GeneratedMessage request,
T emptyResponse) async {
final response = await http.post(
Uri.parse(apiUrl),
headers: {
'Content-Type': 'application/x-protobuf',
},
body: request.writeToBuffer(),
);
emptyResponse.mergeFromBuffer(response.bodyBytes);
return Future.value(emptyResponse);
}
}
这只是简单实现版本,实际要根据业务需求与使用的 rpc
类型对代码进行调整。
api.dart
import 'package:protocols/gen/web.ext.pb.dart';
import 'package:protocols/request.dart';
final Request _request = Request(apiUrl: 'xxx');
WebServiceApi _webServiceApi = WebServiceApi(_request);
Future<ResponseMessage> getResponse(String name) async {
return await _webServiceApi.getResponse(null, RequestMessage(name: name));
}
只需创建 WebServiceApi
实例,并把 Request
实例作为参数传入,即可通过 WebServiceApi
实例调用 web.ext.pb.dart
中的 getResponse
方法。后续只需在项目中引入 api.dart
文件,并调用 getResponse
方法即可。