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 PMResponseKD
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