Skip to content

Getting Started

Welcome to RPC Dart! This guide will help you get up and running with RPC Dart in your Dart or Flutter project.

Add RPC Dart to your project by running the following command:

Terminal window
dart pub add rpc_dart

For additional transport types (HTTP, WebSocket, Isolate), also add:

Terminal window
dart pub add rpc_dart_transports

Let’s create a simple calculator service to demonstrate the core concepts of RPC Dart.

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';
}

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);
}

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);
}
}

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,
);
}
}

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();
}

🚀 Zero-Copy Performance: With InMemory transport, objects are passed 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 between InMemory, HTTP, WebSocket without changing your business logic.