I am looking at a code that I have to work on. And basically I have to add a validation to a listener of a button.
The code has already multiple validations. They are kind of set in a cascade.
The listener of the buttons calls an asyncCallBack method that if everything is ok, on the onsuccess part of the method calls for the next one, an that one on the next one, until it reaches the end and goes to the next page. I am not a fan of this approach because it is kind of messy. What would the best way to do that using best practices.
An example of the code:
Button btnOK = new Button("Aceptar");
btnOK.addListener(Events.Select, new Listener<ButtonEvent>() {
public void handleEvent(ButtonEvent e) {
myService.getInfo1(1, txt, "N",
new AsyncCallback<List<InfoService>>() {
public void onFailure(Throwable caught) {
// goes back
return
}
public void onSuccess(
List<Object> result) {
// do some validation with the result
validation2();
}
}
}
}
public void validation2(){
myService.getDireccionCanalesElectronicos(id, new AsyncCallback<MyResult>() {
public void onSuccess(MyResult result) {
// do some validation with the result
validation3();
}
...
}
}
public void validation3(){
myService.getDireccionCanalesElectronicos(id, new AsyncCallback<MyResult>() {
public void onSuccess(MyResult result) {
// do some validation with the result
validation4();
}
...
}
}
Is there a better way of doing this, it seems messy and hard to follow. Adding another validation is complicated. It doesnt seem like a good practice.
Create 1 method in the servlet that calls all the validation methods and do just one call in the client ?
public void validation()
{
boolean ok = validation1();
if (ok) ok = validation2();
return validation;
}
Using mirco services is sometimes hard to deal with. As #Knarf mentioned, this is a way to go. But sometime you may want to handle the calls on the client side. Another one will be using this tiny framework: sema4g. It will help you to solve your problem.
A solution might look like that:
First create the sem4g commands:
private SeMa4gCommand createGetInfoCommand() {
return new AsyncCommand() {
// create callback
MethodCallbackProxy<List<InfoService>> proxy = new MethodCallbackProxy<List<InfoService>>(this) {
#Override
protected void onProxyFailure(Method method,
Throwable caught) {
// Enter here the code, that will
// be executed in case of failure
}
#Override
protected void onProxySuccess(Method method,
List<InfoService> response) {
// Enter here the code, that will
// be executed in case of success
}
};
#Override
public void execute() {
// That's the place for the server call ...
myService.getInfo1(1, txt, "N", proxy);
}
};
}
do that for all your calls;
private SeMa4gCommand createCommandGetDireccionCanalesElectronicos() {
return new AsyncCommand() {
// create callback
MethodCallbackProxy<MyResult> proxy = new MethodCallbackProxy<MyResult>(this) {
#Override
protected void onProxyFailure(Method method,
Throwable caught) {
// Enter here the code, that will
// be executed in case of failure
}
#Override
protected void onProxySuccess(Method method,
List<MyResult> response) {
// Enter here the code, that will
// be executed in case of success
}
};
#Override
public void execute() {
// That's the place for the server call ...
myService. getDireccionCanalesElectronicos(id, proxy);
}
};
}
Once you have done this for all your calls, create a sema4g context and run it:
try {
SeMa4g.builder()
.addInitCommand(new InitCommand() {
#Override
public void onStart() {
// Enter here your code, that
// should be executed when
// the context is started
})
.addFinalCommand(new FinalCommand() {
#Override
public void onSuccess() {
// Enter here the code, that will
// be executed in case the context
// ended without error
}
#Override
public void onFailure() {
// Enter here the code, that will
// be executed in case the context
// ended with an error
})
.add(createGetInfoCommand())
.add(createCommandGetDireccionCanalesElectronicos())
.build()
.run();
} catch (SeMa4gException e) {
// Ups, something wrong with the context ...
}
For more informations, read the documentation. If you have questions, feel free to ask: SeMa4g Gitter room.
Hope that helps.
Related
I am using mvvm architecture I would like to notify view when volley post request is successful, what i could do is to instantiate ViewModel in appRepository class and then post values to a liveData, but i guess that's not a good approach as I haven't seen a similar practice. Can anyone suggest me a good approach to return my response to ui, or at least notify that post request has been successful.
From fragment/View I trigger this method
// save data to api
checkInViewModel.updateEventPersonEntity(eventPersonsEntity);
ViewModel forwards it to apprespository
public void updateEventPersonEntity(EventPersonsEntity eventPersonsEntity) {
mRepository.updateEventPersonEntity(eventPersonsEntity);
}
AppRepository.Java class
public void updateEventPersonEntity(EventPersonsEntity eventPersonsEntity) {
executor.execute(() -> {
// mDb.eventPersonsDao().update(eventPersonsEntity);
if (isNetworkAvailable(context)) {
post_updateEventPersonEntity(eventPersonsEntity);
}
});
}
private void post_updateEventPersonEntity(EventPersonsEntity eventPersonsEntity) {
Map<String, Object> params = new HashMap<>();
params.put("EventPersonId", eventPersonsEntity.getEventPersonId());
params.put("EventId", eventPersonsEntity.getEventId());
params.put("PersonId", eventPersonsEntity.getPersonId());
params.put("CashStart", parseDoubleToGerman(eventPersonsEntity.getCashStart()));
params.put("CashEnd", parseDoubleToGerman(eventPersonsEntity.getCashEnd()));
params.put("StartingTime", String.valueOf(eventPersonsEntity.getStartingTime()));
params.put("EndingTime", String.valueOf(eventPersonsEntity.getEndingTime()));
params.put("isChekcedIn", eventPersonsEntity.getIsCheckedIn());
params.put("isChekcedOut", eventPersonsEntity.getIsCheckedOut());
JSONObject objRegData = new JSONObject(params);
String eventPersonApi = APP_URL.EVENT_PERSONS_API + eventPersonsEntity.getEventPersonId();
RequestQueueSingleton.getInstance(context).objectRequest(eventPersonApi, Request.Method.PUT, this::onSuccess_updateEventPersonEntity, this::onError, objRegData);
}
private void onError(VolleyError error) {
Log.d(APP_REPOSITORY_TAG, "requestError: " + error);
}
private void onSuccess_updateEventPersonEntity(JSONObject jsonObject) {
// notify ui
}
You can do this same as you did for your success response logic in repository. Simply create new callback interface:
interface OnEventUpdatedListener{
void eventUpdated();
}
Then, update your method to look like this, passing the listener to the actual method that does the work:
public void updateEventPersonEntity(EventPersonsEntity eventPersonsEntity, OnEventUpdatedListener listener) {
mRepository.updateEventPersonEntity(eventPersonsEntity, listener);
}
Pass this inside your:
if (isNetworkAvailable(context)) {
post_updateEventPersonEntity(eventPersonsEntity, listener);
}
After that, in your onSuccess() method simply call:
private void onSuccess_updateEventPersonEntity(JSONObject jsonObject) {
listener.eventUpdated();
}
Finally, you will have the info when the update happens, in the calling site, if you call your repository like this:
updateEventPersonEntity(null, new OnEventUpdatedListener() {
#Override
public void EventUpdated() {
// Do your logic here
}
});
Is there any way to implement an interface in dart/flutter without having to use a class?
Currently, how I implement it is with the code below
class _UserSignupInterface extends _SignupSelectUsernamePageState
implements UserSignupInterface {
#override
void onSuccess() {
_navigateToUserPage();
}
#override
void onError() {
setState(() {
_isSignupClickable = true;
});
}
}
_attemptSignup() {
UserSingleton userSingletonInstance = UserSingleton().getInstance();
UserSignupInterface _userSignupInterface = _UserSignupInterface();
UserSingleton().getInstance().user.username = _username;
UserLoginController.attemptSignup(_userSignupInterface,
userSingletonInstance.user, userSingletonInstance.userDetail, _groupID);
}
However, I would like to implement these interface methods without having to use a class, just as I would in java. Something that would look like the code below.
UserController.attemptSignup(context, new UserSignupRequest() {
#Override
public void onSuccess(User user, UserDetail userDetail, Group group) {
btnContinueWithFacebook.setEnabled(true);
Intent intent = new Intent(context, ScoopActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
progressBar.setVisibility(View.GONE);
startActivity(intent);
}
#Override
public void onFail() {
Log.d(APP.TAG, "Signup request has failed");
btnContinueWithFacebook.setEnabled(true);
progressBar.setVisibility(View.GONE);
/**
* TODO:: Notify user of signup attempt failure
*/
}
}, user, userDetail, group_id);
There is no such feature in Dart. In order to implement an interface, you have to declare a class.
The alternatives is to define the API to accept individual functions instead of a single object, or to declare a helper class which takes the behavior of the necessary methods as constructor arguments.
Example:
class _UserSignupInterface extends _SignupSelectUsernamePageState
implements UserSignupInterface {
void Function(_UserSingupInterface self) _onSuccess;
void Function(_UserSingupInterface self) _onError;
_UserSignupInterface(this._onSuccess, this._onError);
#override
void onSuccess() {
_onSuccess(this);
}
#override
void onError() {
_onError(this);
}
}
Then you can call it as:
... _UserSignupInterface((self) {
self._navigateToUserPage();
}, (self) {
self.setState(() {
self._isSignupClickable = true;
});
})
It's not as pretty as Java, admittedly.
I know this question already has an answer but I would like to add a more neater implementation close to Java inline interface which I normally use.
First, we have the class which acts as our interface:
class HttpRequestCallback {
/// Called when http request is completed
final void Function() onCompleted;
/// Called when http request is successful
/// * [message] is a dynamic object returned by the http server response
final void Function(dynamic message) onSuccess;
/// Called when http request fail
/// * [message] is a dynamic object returned by the http server response
final void Function(dynamic message) onError;
HttpRequestCallback(
{required this.onCompleted,
required this.onSuccess,
required this.onError});
}
Secondly, we have a function that expects the interface as parameter:
Future<void> login(LoginModel model, {HttpRequestCallback? callback}) async {
var response = await httpClient.doPost(app_constants.ApiEndpoints.Login,
body: model.toJson());
// Api request completed
callback?.onCompleted();
if (response.success) {
// Api request successful
callback?.onSuccess(LoginResponseModel.fromJson(
response.message as Map<String, dynamic>));
} else {
// Api request failed
callback?.onError(response.message);
}
}
Finally, we call the function passing our interface as an argument:
...
apiService.login(loginModel,
callback: HttpRequestCallback(
onCompleted: () {
//...
},
onSuccess: (message) {
//...
},
onError: (message) {
//...
}
));
...
I think you are looking for anonymous class in Dart, but it's not supported.
If i understood well what you are trying to do, you can achieve something similar by passing function as parameter in this way:
enum ResultLogin { OK, ERROR }
class Login {
Function _listener; // generic function
Login(listener) {
_listener = listener;
}
void run(){
ResultLogin result = *DO_YOUR_LOGIN_FUNCTION*;
_listener(result);
}
}
class Main {
void doLogin(){
Login myLogin = new Login((ResultLogin result){
switch(result){
case OK:
print("OK");
break;
case ERROR:
print("ERROR");
break;
default:
break;
}
}
);
}
}
In this way you can handle your result and refresh some widget state according to your needs.
I need to show a progress bar while downloanding something from my webservice, because i need to make a fragment transition just when the download was complete. I've tried to many different things, but im still stucked on the start. I got the transition before the download finish
Someone can show me an example or show me a direction from where to look to solve this problem?
public void efetuarLogin() {
loadProgress.setVisibility(View.VISIBLE);
final iRequestsTramita requestsTramita = TramitaService.getInstance().usarServico();
Call<RespostaTramita> callCapturarUG = requestsTramita.getResposta(new LoginTramita(userLogin,userPass));
callCapturarUG.enqueue(new Callback<RespostaTramita>() {
#Override
public void onResponse(Call<RespostaTramita> call, Response<RespostaTramita> response) {
//loadProgress.setVisibility(View.GONE);
if (response.isSuccessful()) {
doing something...
baixarObrasGestor();
loadProgress.setVisibility(View.GONE);
} else {
doing something...
}
}
#Override
public void onFailure(Call<RespostaTramita> call, Throwable t) {
...
}
});
}
public void baixarObrasGestor(){
List<Gestao> listaIdRequisicao = bancoDadosController.gerarListaRequisicaoGeoPB(userLogin);
iRequestsGeoPB requestsGeoPB = GeoPBService.getInstance().usarServico();
//make some requests to webservice
for (Gestao gestao : listaIdRequisicao){
...
Call<List<RespostaGeoPB>> callBaixarObras = requestsGeoPB.baixarObrasGestor(headers, paramRequisicao);
callBaixarObras.enqueue(new Callback<List<RespostaGeoPB>>() {
#Override
public void onResponse(Call<List<RespostaGeoPB>> call, Response<List<RespostaGeoPB>> response) {
...doing something
}
#Override
public void onFailure(Call<List<RespostaGeoPB>> call, Throwable t) {
Log.d("TESTE", "erro: " + t.getMessage());
}
});
}
selecionaUG(); //do the fragment transition
}
Personally I override Callback<T> this provides you option to include all custom events you want to raise like.
public abstract class RetryCallback<T> implements Callback<T> { ... }
If you only want to hear when loading completes this much skleton is enough. But make sure some exception is not raised out of your onResponse or onFailure. I have often seen transition without notice when some exception is raised. Pack your code inside try-catch and see if it is not the problem case.
public void onResponse(Call<T> call, Response<T> response) {
if(!response.isSuccessful()){
// ....
loadingComplete();
return;
}
// ...
loadingComplete();
}
#Override
public void onFailure(Call<T> call, Throwable t) {
// ...
loadingComplete();
}
I'm trying to find a way to handle asynchronous network requests in Swift. My plan is to isolate these calls in their own class, so I need a way to handle callbacks. In Android, I'm doing something like the following using an Interface:
apiService.fetch(data, new Callback() {
#Override
public void onResponse(Response r) {
// success
}
#Override
public void onFailure(Error e) {
// error
}
});
Can someone point me in the direction on how I can handle this similarly in Swift 3? Thanks!
It's possible to have multiple completion handlers. Here is a short example:
func request(url:String, success:#escaping(Any) -> Void, failure:#escaping(Any?) -> Void)
{
let task = URLSession.shared.dataTask(with: URL.init(string: url)!) { (data, response, error) in
if let responseError = error
{
failure(responseError)
}
else if let responseData = data //Make additional checks if there is an error
{
success(responseData) //Call when you are sure that there is no error
}
else
{
failure(nil)
}
}
task.resume()
}
Example of usage:
self.request(url: "https://jsonplaceholder.typicode.com/posts", success: { (data) in
//Do if success
}) { (error) in
//Do if error
}
I am relatively new to RXJava in general (really only started using it with RXJava2), and most documentation I can find tends to be RXJava1; I can usually translate between both now, but the entire Reactive stuff is so big, that it's an overwhelming API with good documentation (when you can find it). I'm trying to streamline my code, an I want to do it with baby steps. The first problem I want to solve is this common pattern I do a lot in my current project:
You have a Request that, if successful, you will use to make a second request.
If either fails, you need to be able to identify which one failed. (mostly to display custom UI alerts).
This is how I usually do it right now:
(omitted the .subscribeOn/observeOn for simplicity)
Single<FirstResponse> first = retrofitService.getSomething();
first
.subscribeWith(
new DisposableSingleObserver<FirstResponse>() {
#Override
public void onSuccess(final FirstResponse firstResponse) {
// If FirstResponse is OK…
Single<SecondResponse> second =
retrofitService
.getSecondResponse(firstResponse.id) //value from 1st
.subscribeWith(
new DisposableSingleObserver<SecondResponse>() {
#Override
public void onSuccess(final SecondResponse secondResponse) {
// we're done with both!
}
#Override
public void onError(final Throwable error) {
//2nd request Failed,
}
});
}
#Override
public void onError(final Throwable error) {
//firstRequest Failed,
}
});
Is there a better way to deal with this in RXJava2?
I've tried flatMap and variations and even a Single.zip or similar, but I'm not sure what the easiest and most common pattern is to deal with this.
In case you're wondering FirstRequest will fetch an actual Token I need in the SecondRequest. Can't make second request without the token.
I would suggest using flat map (And retrolambda if that is an option).
Also you do not need to keep the return value (e.g Single<FirstResponse> first) if you are not doing anything with it.
retrofitService.getSomething()
.flatMap(firstResponse -> retrofitService.getSecondResponse(firstResponse.id)
.subscribeWith(new DisposableSingleObserver<SecondResponse>() {
#Override
public void onSuccess(final SecondResponse secondResponse) {
// we're done with both!
}
#Override
public void onError(final Throwable error) {
// a request request Failed,
}
});
This article helped me think through styles in how I structure RxJava in general. You want your chain to be a list of high level actions if possible so it can be read as a sequence of actions/transformations.
EDIT
Without lambdas you can just use a Func1 for your flatMap. Does the same thing just a lot more boiler-plate code.
retrofitService.getSomething()
.flatMap(new Func1<FirstResponse, Observable<SecondResponse> {
public void Observable<SecondResponse> call(FirstResponse firstResponse) {
return retrofitService.getSecondResponse(firstResponse.id)
}
})
.subscribeWith(new DisposableSingleObserver<SecondResponse>() {
#Override
public void onSuccess(final SecondResponse secondResponse) {
// we're done with both!
}
#Override
public void onError(final Throwable error) {
// a request request Failed,
}
});
Does this not work for you?
retrofitService
.getSomething()
.flatMap(firstResponse -> retrofitService.getSecondResponse(firstResponse.id))
.doOnNext(secondResponse -> {/* both requests succeeded */})
/* do more stuff with the response, or just subscribe */