Skip to content

Instantly share code, notes, and snippets.

@DFreds
Last active February 7, 2018 04:45
Show Gist options
  • Select an option

  • Save DFreds/edec5854b89e6529f277c392c3cea081 to your computer and use it in GitHub Desktop.

Select an option

Save DFreds/edec5854b89e6529f277c392c3cea081 to your computer and use it in GitHub Desktop.
Kotlin coroutine await extension for Google Cloud Firestore
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
// init view code....
viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
viewModel.response.observe(this, Observer { processResponse(it) })
viewModel.loadMyData()
}
private fun processResponse(response: MyResponse<List<MyData>>?) = when (response?.status) {
MyResponse.Status.LOADING -> showLoading()
MyResponse.Status.SUCCESS -> handleSuccess(response)
MyResponse.Status.ERROR, null -> handleError()
}
private fun showLoading() {
// show loading indicator
}
private fun handleSuccess(response: MyResponse<List<MyData>>) {
// handle success
}
private fun handleError() {
// handle error
}
}
class MainRepository private constructor() {
private object Holder {
val INSTANCE = MainRepository()
}
companion object {
val instance: MainRepository by lazy { Holder.INSTANCE }
}
suspend fun getMyData(): List<MyData>? {
val firestore = FirebaseFirestore.getInstance()
return firestore.collection("mydata")
.get()
.awaitGet()
}
}
class MainViewModel : ViewModel() {
private val repository = MainRepository.instance
val response: MutableLiveData<MyResponse<List<MyData>>> = MutableLiveData()
fun loadMyData() = async(UI) {
response.value = MyResponse.loading()
val result = async {
repository.getMyData()
}.await()
when (result) {
null -> response.value = MyResponse.error(Throwable("Null data returned"))
else -> response.value = MyResponse.success(result)
}
}
}
suspend fun Task<Void>.awaitSet(): MyResponse<Void> {
return suspendCancellableCoroutine { continuation ->
this.addOnCompleteListener { task: Task<Void> ->
continuation.resume(
if (task.isSuccessful) {
MyResponse.success(task.result)
} else {
MyResponse.error(task.exception ?: Throwable("Unknown error"))
}
)
}
}
}
suspend inline fun <reified TResult> Task<QuerySnapshot>.awaitGet(): List<TResult>? {
return suspendCancellableCoroutine { continuation ->
this.addOnCompleteListener { task: Task<QuerySnapshot> ->
continuation.resume(
if (task.isSuccessful) {
task.result.toObjects(TResult::class.java)
} else {
null
}
)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment