geekdroid-firebase/src/main/java/com/geekorum/geekdroid/gms/Tasks.kt
changeset 1 831cffa9c991
child 20 5d8a0555733d
equal deleted inserted replaced
0:fef46dce2812 1:831cffa9c991
       
     1 /**
       
     2  * Geekdroid is a utility library for development on the Android
       
     3  * Platform.
       
     4  *
       
     5  * Copyright (C) 2017-2020 by Frederic-Charles Barthelery.
       
     6  *
       
     7  * This file is part of Geekdroid.
       
     8  *
       
     9  * Geekdroid is free software: you can redistribute it and/or modify
       
    10  * it under the terms of the GNU General Public License as published by
       
    11  * the Free Software Foundation, either version 3 of the License, or
       
    12  * (at your option) any later version.
       
    13  *
       
    14  * Geekdroid is distributed in the hope that it will be useful,
       
    15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    17  * GNU General Public License for more details.
       
    18  *
       
    19  * You should have received a copy of the GNU General Public License
       
    20  * along with Geekdroid.  If not, see <http://www.gnu.org/licenses/>.
       
    21  */
       
    22 package com.geekorum.geekdroid.gms
       
    23 
       
    24 import com.google.android.gms.tasks.Task
       
    25 import kotlinx.coroutines.CancellationException
       
    26 import kotlinx.coroutines.CompletableDeferred
       
    27 import kotlinx.coroutines.Deferred
       
    28 import kotlinx.coroutines.suspendCancellableCoroutine
       
    29 import kotlin.coroutines.resume
       
    30 import kotlin.coroutines.resumeWithException
       
    31 import com.google.android.play.core.tasks.Task as PlayCoreTask
       
    32 
       
    33 /**
       
    34  * Await for the result of a [Task]
       
    35  */
       
    36 @Deprecated("Use kotlinx-coroutines-play-services")
       
    37 suspend fun <T> Task<T>.await(): T {
       
    38     try {
       
    39         if (isComplete) return result as T
       
    40     } catch (e: RuntimeException) {
       
    41         return suspendCancellableCoroutine {
       
    42             it.resumeWithException(e.cause ?: e)
       
    43         }
       
    44     }
       
    45 
       
    46     return suspendCancellableCoroutine { cont ->
       
    47         addOnCompleteListener { task ->
       
    48             if (task.isSuccessful) {
       
    49                 cont.resume(task.result!!)
       
    50             } else {
       
    51                 cont.resumeWithException(task.exception!!)
       
    52             }
       
    53         }
       
    54     }
       
    55 }
       
    56 
       
    57 /**
       
    58  * Await for the nullable result of a [Task]
       
    59  * As [Task] is a Java API without proper nullability annotations,
       
    60  * use this method if you know the task can returns null
       
    61  */
       
    62 @Deprecated("Use kotlinx-coroutines-play-services")
       
    63 suspend fun <T> Task<T>.awaitNullable(): T? {
       
    64     try {
       
    65         if (isComplete) return result
       
    66     } catch (e: RuntimeException) {
       
    67         return suspendCancellableCoroutine {
       
    68             it.resumeWithException(e.cause ?: e)
       
    69         }
       
    70     }
       
    71 
       
    72     return suspendCancellableCoroutine { cont ->
       
    73         addOnCompleteListener { task ->
       
    74             if (task.isSuccessful) {
       
    75                 cont.resume(task.result)
       
    76             } else {
       
    77                 cont.resumeWithException(task.exception!!)
       
    78             }
       
    79         }
       
    80     }
       
    81 }
       
    82 
       
    83 
       
    84 /**
       
    85  * Converts this task to an instance of [Deferred].
       
    86  */
       
    87 fun <T> PlayCoreTask<T>.asDeferred(): Deferred<T> {
       
    88     if (isComplete) {
       
    89         val e = exception
       
    90         return if (e == null) {
       
    91             @Suppress("UNCHECKED_CAST")
       
    92             CompletableDeferred<T>().apply { complete(result as T) }
       
    93         } else {
       
    94             CompletableDeferred<T>().apply { completeExceptionally(e) }
       
    95         }
       
    96     }
       
    97 
       
    98     val result = CompletableDeferred<T>()
       
    99     addOnCompleteListener {
       
   100         val e = it.exception
       
   101         if (e == null) {
       
   102             @Suppress("UNCHECKED_CAST")
       
   103             result.complete(it.result as T)
       
   104         } else {
       
   105             result.completeExceptionally(e)
       
   106         }
       
   107     }
       
   108     return result
       
   109 }
       
   110 
       
   111 /**
       
   112  * Awaits for completion of the task without blocking a thread.
       
   113  *
       
   114  * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
       
   115  * stops waiting for the completion stage and immediately resumes with [CancellationException].
       
   116  */
       
   117 suspend fun <T> PlayCoreTask<T>.await(): T {
       
   118     // fast path
       
   119     if (isComplete) {
       
   120         val e = exception
       
   121         return if (e == null) {
       
   122             @Suppress("UNCHECKED_CAST")
       
   123             result as T
       
   124         } else {
       
   125             throw e
       
   126         }
       
   127     }
       
   128 
       
   129     return suspendCancellableCoroutine { cont ->
       
   130         addOnCompleteListener {
       
   131             val e = exception
       
   132             if (e == null) {
       
   133                 @Suppress("UNCHECKED_CAST")
       
   134                 cont.resume(result as T)
       
   135             } else {
       
   136                 cont.resumeWithException(e)
       
   137             }
       
   138         }
       
   139     }
       
   140 }
       
   141