Getting started¶
Welcome to RPC Dart! This guide walks you through installing the package and building your first service.
Installation¶
Dart¶
dart pub add rpc_dart
Flutter¶
flutter pub add rpc_dart
For additional transport types (HTTP, WebSocket, isolate) also add:
dart pub add rpc_dart_transports
Your first RPC service¶
Let's create a simple calculator service to demonstrate the core concepts of RPC Dart.
1. Define the contract¶
First, define the service contract with constants for service and method names:
// calculator_contract.dart
abstract interface class ICalculatorContract {
static const name = 'Calculator';
static const methodAdd = 'add';
}
2. Create request/response models¶
Define the data models for your RPC calls:
// models.dart
class AddRequest {
final double a;
final double b;
AddRequest(this.a, this.b);
}
class AddResponse {
final double result;
AddResponse(this.result);
}
3. Implement the server (responder)¶
Create a responder that handles incoming RPC calls:
// calculator_responder.dart
import 'package:rpc_dart/rpc_dart.dart';
final class CalculatorResponder extends RpcResponderContract {
CalculatorResponder() : super(ICalculatorContract.name);
@override
void setup() {
// Register unary method handler
addUnaryMethod<AddRequest, AddResponse>(
methodName: ICalculatorContract.methodAdd,
handler: _add,
);
}
Future<AddResponse> _add(AddRequest request, {RpcContext? context}) async {
final result = request.a + request.b;
return AddResponse(result);
}
}
4. Create the client (caller)¶
Implement a client that calls the RPC methods:
// calculator_caller.dart
import 'package:rpc_dart/rpc_dart.dart';
final class CalculatorCaller extends RpcCallerContract {
CalculatorCaller(RpcCallerEndpoint endpoint)
: super(ICalculatorContract.name, endpoint);
Future<AddResponse> add(AddRequest request) {
return callUnary<AddRequest, AddResponse>(
methodName: ICalculatorContract.methodAdd,
request: request,
);
}
}
5. Put it all together¶
Now let's create a complete example that sets up the transport, endpoints, and makes an RPC call:
// main.dart
import 'package:rpc_dart/rpc_dart.dart';
void main() async {
// Create InMemory transport pair
final (clientTransport, serverTransport) = RpcInMemoryTransport.pair();
// Setup responder endpoint
final responder = RpcResponderEndpoint(transport: serverTransport);
responder.registerServiceContract(CalculatorResponder());
responder.start();
// Setup caller endpoint
final caller = RpcCallerEndpoint(transport: clientTransport);
// Create calculator client
final calculator = CalculatorCaller(caller);
// Make RPC call
final result = await calculator.add(AddRequest(10, 5));
print('10 + 5 = ${result.result}'); // Output: 10 + 5 = 15.0
// Cleanup
await caller.close();
await responder.close();
}
Key benefits¶
- 🚀 Zero-copy performance: InMemory transport passes objects directly without serialization overhead.
- 🔒 Type safety: All RPC calls are strongly typed, catching errors at compile time.
- 🧪 Easy testing: InMemory transport makes unit and integration testing straightforward.
- 🔌 Transport agnostic: Switch transports without changing business logic.
Next steps¶
- Learn the core concepts
- Explore the architecture
- Browse examples on GitHub
- Open an issue on GitHub if you have questions