Search code examples
androidgrpcokhttp

Why no NetworkOnMainThreadException when using GRPC on android?


I have the below code inside my activity's onCreate()

fun onCreate() {

        val channel = AndroidChannelBuilder.forAddress(someEndPoint, port)
            .context(applicationContext)
            .build()
    
        val stub: ClientLoggerGrpc.ClientLoggerBlockingStub =
                ClientLoggerGrpc.newBlockingStub(channel)
    
        val request = Service.ClientLogRequest.newBuilder()
            .setMsg("Hello world!")
            .setLogLevel(Service.LogLevel.Info)
            .build()
    
        val response = stub.log(request)
    
        Log.d(TAG, "onCreate: $response")
}

As we see here, I'm not switching to a background thread and I'm using a BlockingStub but it still doesn't crash the app with NetworkOnMainThreadException.

Does GRPC auto switch to BG thread, even when using a blocking stub or does GRPC do things differently that GRPC is able to bypass the check which throws the NetworkOnMainThreadException?


Solution

  • gRPC Java is natively async. io.grpc.ClientCall, as seen when making interceptors, is the API into gRPC's core to perform RPCs and is an async API with callbacks. The stubs layer on top of ClientCall and convert it into a blocking API. The I/O is done on two separate threads: one for reading, one for writing.

    The majority of HTTP/2 clients behave similarly of handling I/O separately, since HTTP/2 multiplexes multiple exchanges onto a single connection and requires reading simultaneously with writing.