Travis Griggs
02/05/2021, 8:57 PMjefbit
02/05/2021, 8:58 PMLarry Schiefer
02/05/2021, 8:59 PMBrian Dupuis
02/05/2021, 8:59 PMLarry Schiefer
02/05/2021, 9:03 PMBrian Dupuis
02/05/2021, 9:05 PMBen Butterworth
02/05/2021, 9:47 PMKD
02/05/2021, 9:56 PMCall<T>
and handle the error
or success
case in that listener.
Then once you are comfortable with coroutines, simply remove that Call<T>
and mark you functions suspend
. However, one caveat is that even though coroutines look simple, once you start digging into it thereâs a lot of implementation details that went into it.Ben Butterworth
02/05/2021, 9:56 PMKD
02/05/2021, 9:57 PMBen Butterworth
02/05/2021, 9:57 PMsuspend
, I would replace Call
with Response
though, as you want to check statusCode and stuff?KD
02/05/2021, 9:58 PMBen Butterworth
02/05/2021, 10:01 PMKD
02/05/2021, 10:02 PMKD
02/05/2021, 10:02 PMBen Butterworth
02/05/2021, 10:02 PMKD
02/05/2021, 10:02 PMBen Butterworth
02/05/2021, 10:03 PMKD
02/05/2021, 10:03 PMBen Butterworth
02/05/2021, 10:03 PMKD
02/05/2021, 10:04 PMsuspend
functions on retrofit. my bad!Ben Butterworth
02/05/2021, 10:05 PMResponse<T>
, just T
?KD
02/05/2021, 10:05 PMsuspend
and only provide what you want in returnBen Butterworth
02/05/2021, 10:07 PMBen Butterworth
02/05/2021, 10:07 PMResponse
for suspend functionsTravis Griggs
02/05/2021, 10:07 PMKD
02/05/2021, 10:08 PMKD
02/05/2021, 10:08 PMBen Butterworth
02/05/2021, 10:08 PMKD
02/05/2021, 10:10 PMfun fetchAuthenticationFlow(credentials: Credentials) = flow {
val response = accountService.loginWithCredentials(credentials)
if (response.isSuccessful) {
val authentication = response.body() ?: throw NullPointerException()
emit(authentication)
} else throw IllegalAccessException("Unsuccessful response received.")
}.flowOn(<http://Dispatchers.IO|Dispatchers.IO>)
jefbit
02/05/2021, 10:10 PMBen Butterworth
02/05/2021, 10:11 PMResponse
?Ben Butterworth
02/05/2021, 10:11 PMKD
02/05/2021, 10:11 PMT
in place of Response<T>
. I assumed you were asking Call
insteadBen Butterworth
02/05/2021, 10:12 PMResponse
KD
02/05/2021, 10:13 PMResponse
wrapper though. https://proandroiddev.com/suspend-what-youre-doing-retrofit-has-now-coroutines-support-c65bd09ba067 you can simply return the objectKD
02/05/2021, 10:14 PMBen Butterworth
02/05/2021, 10:15 PMResponse
when using coroutines should be the defaultjefbit
02/05/2021, 10:15 PMBen Butterworth
02/05/2021, 10:17 PMResponse
into a result class, but i made my own sealed class Result
because i didnt know about this. You still have to create it donât you (retrofit doesnât help here)?KD
02/05/2021, 10:22 PMResult
or custom ones has to offer.KD
02/05/2021, 10:23 PMFlow
you can react to your value and provide appropriate response to your views. This ways all the viewState logic gets nicely wrapped in the Flow
or to put it in a nice manner, in one place. Then again, its my personal preference. One should always go with what they think is best for the project đ đjefbit
02/05/2021, 10:25 PMBen Butterworth
02/05/2021, 10:27 PMResult
. Isnât using flow/ rx to pass data to Ui layer the same as using Result, just a different implementation.KD
02/05/2021, 10:29 PMResult
rail monad creates a lot of noise in your layers. Youâd have to propagate this Result
all the way to the presentation layer to your viewModel
. That means your domain
layer is now polluted with Result
monad, and your business logic is now tightly coupled with this paradigm.Ben Butterworth
02/05/2021, 10:29 PMKD
02/05/2021, 10:30 PMBen Butterworth
02/05/2021, 10:30 PMBen Butterworth
02/05/2021, 10:30 PMjefbit
02/05/2021, 10:30 PMKD
02/05/2021, 10:31 PMResult
monad or not.KD
02/05/2021, 10:31 PMjefbit
02/05/2021, 10:32 PMjefbit
02/05/2021, 10:32 PMBen Butterworth
02/05/2021, 10:33 PMif an error occurred. Your viewmodel implementation has to deal with that case.But the UI might to display something based off this error. I guess if an error fails for you, you call a global function to warn the user about an error? Anyway, it looks like youâve got the same pollution and tight coupling with flow. I donât see any differences @KD?
KD
02/05/2021, 10:33 PMResult
monad where you have to add a new state.KD
02/05/2021, 10:34 PMSuccess
and Failure
, adding a third state would need you to make changes everywhere where you are unwrapping the Result
.KD
02/05/2021, 10:35 PMcatch
operator in the flow has when
clause that can catch all the different exceptions thrown in its scope. No need to make changes in domain or data layer.Ben Butterworth
02/05/2021, 10:39 PMResult
, you can add a third state. Of course, the Result can just have 2 subclasses (Success and Failure), which is what flow values youâre using is limited too as well? The Failure
wraps the exception, so it behaves the same as what i think you mean when you say catching exceptions in flow.
Im not familiar with flow, but I can have exhaustive when
expressions and statements too, thats why I use a sealed class Result
?Ben Butterworth
02/05/2021, 10:40 PMKD
02/05/2021, 10:40 PMException
in Failure
and your Success
returns the good response, Why not elimiate Result
monad, return good response as it is, and throw the exceptions for bad case.KD
02/05/2021, 10:41 PMException
in another wrapper class. What are we achieving by it, when we get two choices in the end anways.Ben Butterworth
02/05/2021, 10:42 PMKD
02/05/2021, 10:42 PMResult
monad. Throw RecoverableException
and NonRecoverableException
. Havenât yet seen a case where Result
monad can do a thing that using exceptions
cant. And if i can achieve the same result without using a Result
monad, then naturally i will go with that, no?Ben Butterworth
02/05/2021, 10:46 PMwhen
statement can be exhaustive/ safeTravis Griggs
02/05/2021, 10:46 PMKD
02/05/2021, 10:48 PMwhen
clause will help you but if youâve reached a point where your code depends on when
clause suggestion by IDE then there are bigger issue in play. As far as try catches go, thereâs only flow catch
operator with when
clause, and now that i think of it, what is stopping one from making a sealed class hierarchy of exceptions
that your project uses. see, result
monad has nothing that exceptions
cant do.Ben Butterworth
02/05/2021, 10:49 PMinterface
you write + some converters allows your Service
to reduce the code in AndroidBen Butterworth
02/05/2021, 10:53 PMswitch/when
on that state. Iâll have to see some code to continue discussing this though.Ben Butterworth
02/05/2021, 10:58 PMKD
02/05/2021, 10:59 PMresult
monad in the data layer. So this transitive dependency will always be there, and puts the conversation on a tangent.Travis Griggs
02/05/2021, 10:59 PMTravis Griggs
02/05/2021, 11:00 PMBen Butterworth
02/05/2021, 11:01 PMOkHttpClient client = new OkHttpClient();
String run(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}
KD
02/05/2021, 11:01 PMBen Butterworth
02/05/2021, 11:02 PMKD
02/05/2021, 11:02 PMretrofit
though, given its an industry standard.KD
02/05/2021, 11:04 PMTravis Griggs
02/05/2021, 11:06 PMTravis Griggs
02/06/2021, 12:33 AMR
were suddenly unresolvable. I dove into okhttp. Making a fungible shim which substitutes blocks in for the Response/Error classes brought me the quick one liner approach I was looking forTravis Griggs
02/06/2021, 12:33 AM