LaVOZs

The World’s Largest Online Community for Developers

'; android - Use of Either<L,R> with Firestore - LavOzs.Com

I'm trying to use Either with Firestore , the function I have is this one

fun setDataIntoFirestore(data: HashMap<String,Any>): Either<Failure,Boolean>{
         db.collection("test")
            .add(data)
            .addOnSuccessListener {
                //Here I need Either.Right(true);
            }
            .addOnFailureListener {
                Log.d("FirestoreData", "Failure: " + it.message)
                //Here I want to add Either.Left(it)
            }
    }

I'm trying to do this because I want to notify my view when the data has been added to the database, but when I mark the function to return Either I need to return that type and I cant return anything inside the Task that is suggesting me.

Any ideas on how to implement this ?

I'm calling this method from my use case like this

class SendProductUseCase: UseCase<Boolean, HashMap<String, Any>>() {

    private val repo = SendProductRepo()

    override suspend fun run(params: HashMap<String, Any>): Either<Failure, Boolean> {
        return repo.setDataIntoFirestore(params)
    }

}

And UseCase is a generic UseCase for each one

abstract class UseCase<out Type, in Params> where Type : Any {

    abstract suspend fun run(params: Params): Either<Failure, Type>

    operator fun invoke(params: Params, onResult: (Either<Failure, Type>) -> Unit = {}) {
        val job = GlobalScope.async(Dispatchers.Default) { run(params) }
        GlobalScope.launch(Dispatchers.Main) { onResult(job.await()) }
    }

    class None
}

Thanks

You can use interface to make it return what you want OR I'd prefer to send Higher order function and use it where you want.

your code will be something like this

  fun setDataIntoFirestore(data: HashMap<String,Any> , retValue : (Either<Failure,Boolean>) -> (Unit)){
    db.collection("test")
        .add(data)
        .addOnSuccessListener {
            retValue.invoke(Either.Right(true))
        }
        .addOnFailureListener {
            Log.d("FirestoreData", "Failure: " + it.message)
            //Here I want to add Either.Left(it)
        }
}

you may find complication error but this to demonstrate my idea

Both onScuccess() and onFailure() methods are asynchronous meaning that each one of them will fire only when the data is committed to, or rejected by the Firebase servers. So it will take some time so one or the other method will be triggered and there are no guarantees about how long it will take. Depending on your connection speed and the state, it may take from a few hundred milliseconds even to a few seconds. So there is no way you can return an object of type Either<Failure,Boolean> as result of a method. To solve this, I recommend you see the last part of my anwser from this post in which I have explained how it can be done using a custom callback.

P.S. There is an excelent video where Doug Stevenson explains in practic, how you can achieve this using LiveData:

Related
Moshi's Custom Adapter with RxAndroid & Retrofit & Kotlin
What is firestore Reference data type good for?
invoke() on out-projected Function object
Could not deserialize object. Failed to convert value of type java.util.Date to String
Insert Firestore data into pickerview
Cloud Firestore node.js invalid use of type “object” as a Firestore argument
Chaining Firebase Firestore documents/collections
Defining acceptable lexicographic similarity of Firestore document IDs
How to initialize Cloud Firestore Bean to use throughout all packages?