runWithClient<R> function

R runWithClient<R>(
  1. R body(),
  2. Client clientFactory(), {
  3. ZoneSpecification? zoneSpecification,
})

Runs body in its own Zone with the Client returned by clientFactory set as the default Client.

For example:

class MyAndroidHttpClient extends BaseClient {
  @override
  Future<http.StreamedResponse> send(http.BaseRequest request) {
    // your implementation here
  }
}

void main() {
 var clientFactory = Client.new; // Constructs the default client.
 if (Platform.isAndroid) {
    clientFactory = MyAndroidHttpClient.new;
 }
 runWithClient(myFunction, clientFactory);
}

void myFunction() {
  // Uses the `Client` configured in `main`.
  final response = await get(Uri.https('www.example.com', ''));
  final client = Client();
}

The Client returned by clientFactory is used by the Client.new factory and the convenience HTTP functions (e.g. http.get). If clientFactory returns Client() then the default Client is used.

When used in the context of Flutter, runWithClient should be called before WidgetsFlutterBinding.ensureInitialized because Flutter runs in whatever Zone was current at the time that the bindings were initialized.

runApp calls WidgetsFlutterBinding.ensureInitialized so the easiest approach is to call that in body:

void main() {
 var clientFactory = Client.new; // Constructs the default client.
 if (Platform.isAndroid) {
    clientFactory = MyAndroidHttpClient.new;
 }
 runWithClient(() => runApp(const MyApp()), clientFactory);
}

If runWithClient is used and the environment defines no_default_http_client=true then generated binaries may be smaller e.g.

$ flutter build appbundle --dart-define=no_default_http_client=true ...
$ dart compile exe --define=no_default_http_client=true ...

If no_default_http_client=true is set then any call to the Client factory (i.e. Client()) outside of the Zone created by runWithClient will throw StateError.

Implementation

R runWithClient<R>(R Function() body, Client Function() clientFactory,
        {ZoneSpecification? zoneSpecification}) =>
    runZoned(body,
        zoneValues: {#_clientToken: Zone.current.bindCallback(clientFactory)},
        zoneSpecification: zoneSpecification);