Home > Software design >  Do the kotlin extension functions in com.android.billingclient:billing-ktx dispatch to Dispatchers.I
Do the kotlin extension functions in com.android.billingclient:billing-ktx dispatch to Dispatchers.I

Time:09-01

Reading the documentation for the billing client, there is a section entitled Querying with Kotlin extensions. The example shown includes a dispatch to Dispatchers.IO like this:

val productDetailsResult = withContext(Dispatchers.IO) {
    billingClient.queryProductDetails(params.build())
}

The withContext is shown on other suspending functions as well. queryProductDetails in the ktx lib and the others are all suspending functions. Why do the docs include withContext? I can't imagine the purpose of making a suspending function that just blocked the thread, it should internally dispatch to Dispatchers.IO in my opinion, rendering the withContext calls in the example code superfluous.

Is my assessment correct, can I omit the withContext blocks without blocking the Main thread (assuming the calling context is on Dispatchers.Main)? I wasn't able to determine what it was doing with the debugger, and there doesn't seem to be any documentation on the extension functions.

What I want to write is just:

val productDetailsResult = billingClient.queryProductDetails(params.build())

CodePudding user response:

The decompiled Java code of queryProductDetails extension function looks like the following:

   @Nullable
   @RecentlyNonNull
   public static final Object queryProductDetails(@RecentlyNonNull BillingClient $this$queryProductDetails, @RecentlyNonNull QueryProductDetailsParams params, @RecentlyNonNull Continuation $completion) {
      final CompletableDeferred var3 = CompletableDeferredKt.CompletableDeferred$default((Job)null, 1, (Object)null);
      ProductDetailsResponseListener var4 = new ProductDetailsResponseListener() {
         public final void onProductDetailsResponse(BillingResult billingResult, List productDetailsList) {
            Intrinsics.checkNotNullExpressionValue(billingResult, "billingResult");
            ProductDetailsResult var3x = new ProductDetailsResult(billingResult, productDetailsList);
            var3.complete(var3x);
         }
      };
      $this$queryProductDetails.queryProductDetailsAsync(params, var4);
      return var3.await($completion);
   }

We can see that it uses queryProductDetailsAsync under the hood, so it runs asynchronously. Therefore we can conclude that the call is not blocking and we don't need to wrap billingClient.queryProductDetails(params.build()) into withContext(Dispatchers.IO):

val productDetailsResult = billingClient.queryProductDetails(params.build())
  • Related