How to return httpResponse result LIbGDX - java

So I have been trying to return the content grabbed from httpResponse from a class, however, im not very successful at the moment.
String requestContent = null;
Net.HttpRequest httpRequest;
httpRequest = new Net.HttpRequest(Net.HttpMethods.GET);
httpRequest.setUrl("https://api.parse.com/1/classes/gamerooms/");
System.out.println(Parse.getRestAPIKey() + Parse.getApplicationId());
httpRequest.setHeader("X-Parse-Application-Id", Parse.getApplicationId());
httpRequest.setHeader("X-Parse-REST-API-Key", Parse.getRestAPIKey());
httpRequest.setContent(requestContent);
Gdx.net.sendHttpRequest(httpRequest, new Net.HttpResponseListener() {
#Override
public void handleHttpResponse(Net.HttpResponse httpResponse) {
content = httpResponse.getResultAsString();
}
#Override
public void failed(Throwable t) {
}
#Override
public void cancelled() {
}
});
return content;
}
When I return content, it is empty but when i print the content in handleHttpResponse, i can see it there. Any solutions?

The problem is, that it is handled like a Thread. So when you're returning the content, the answer maybe not already arrived. So you must handle the result in the handleHttpResponse method. If you don't want all the code in that method, you could also call a function.
Also because you're in a Thread I think you should call Gdx.app.postRunnable(Runnable runnable) if you want to change something in the code, which you shouldn't while you are in the render method or need OpenGL context. The Runnable will be called directly before the render method. Threading libGdx

Related

How to notify UI on volley success MVVM architecture

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
}
});

how to url calling return from list function with retrofit

i tried to return list from the url that i get with retrofit. it works and i get the data but it wont return.
this is my code
public List<MovieResponse> loadCourses() {
ArrayList<MovieResponse> list = new ArrayList<>();
ApiServices apiService =
NetworkClient.getRetrofitClient().create(ApiServices.class);
Call<MovieResult> call = apiService.getMovies();
call.enqueue(new Callback<MovieResult>() {
#Override
public void onResponse(Call<MovieResult> call, Response<MovieResult> response) {
if (response.body() != null) {
ArrayList<MovieResponse> movies = new ArrayList<>();
movies = response.body().getResults();
Log.d("",""+movies);
list.addAll(movies);
Log.d("",""+list);
}
}
#Override
public void onFailure(Call<MovieResult> call, Throwable t) {
// Log error here since request failed
Log.e("error", t.toString());
}
});
return list;
}
when i print list inside onResponse it works and there are the data. but when i return it or trying to print list outside onResponse for example below ArrayList<MovieResponse> list = new ArrayList<>(); it not show the data.
please help what is actually wrong with it. i really appreciate it.
The simplest way is to define your movies list directly inside activity or fragment(in other words, a field member of the class).
It's not a good idea to return data from an asynchronous method.
Change the return type of the loadCourses method to void and instantiate the filed movies inside onResponse().
public class SomeActivity extends AppCompatActivity {
private ArrayList<MovieResponse> movies = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_some);
}
public void loadCourses() {
ApiServices apiService =
NetworkClient.getRetrofitClient().create(ApiServices.class);
Call<MovieResult> call = apiService.getMovies();
call.enqueue(new Callback<MovieResult>() {
#Override
public void onResponse(Call<MovieResult> call, Response<MovieResult> response) {
if (response.body() != null) {
movies = response.body().getResults();
...
}
}
#Override
public void onFailure(Call<MovieResult> call, Throwable t) {
...
}
});
}
}
It is because you are making asynchronous call which is being handled by a separate thread. So after call.enqueue(), the main thread directly jumps to return statement without waiting for API response, that's why you are getting empty list.
Assuming your API takes 1 sec to respond,
just for an experiment, you can try adding a sleep() for 3 sec right before your return statement, it should return all the movies.
If you must return from the method then go for retrofit synchronous call.
To make a sync call create a new thread in main thread and make call from there, it is not allowed to make network call from main thread because it blocks the thread.

Validating multiple asyncronous methods in GWT

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.

Java function returns empty string [duplicate]

This question already has answers here:
How to use Jsoup with Volley?
(3 answers)
Closed 6 years ago.
I'm trying to parse data from my server in Java with jsoup. I wrote a new function and it should return data in string format, but it returns blank string. Here is my code:
public String doc;
public String pare(final String url){
Thread downloadThread = new Thread() {
public void run() {
try {
doc = Jsoup.connect(url).get().toString();
}
catch (IOException e) {
e.printStackTrace();
}
}
};
downloadThread.start();
return doc;
}
You're returning the doc object immediately, before the thread has had a chance to add any data to it, so it should be no surprise that this returns empty. You can't return threaded information in this way, and instead will need to use some type of call-back mechanism, one that notifies you when the thread is done and when data is ready to be consumed.
On android platform, you shouldn't ask Jsoup to download anything for you. Under the hood, Jsoup make use of HttpUrlConnection. This class is notoriously slow and has some known issues.
Use a faster alternative instead: Volley.
Here is the function in your post taking advantage of Volley. In the following sample code, I'm using a CountDownLatch to wait for the data.
private static RequestQueue myRequestQueue = null;
public String pare(final String url) throws Exception {
final String[] doc = new String[1];
final CountDownLatch cdl = new CountDownLatch(1);
StringRequest documentRequest = new StringRequest( //
Request.Method.GET, //
url, //
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
doc[0] = Jsoup.parse(response).html();
cdl.coutDown();
}
}, //
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("MyActivity", "Error while fetching " + url, error);
}
} //
);
if (myRequestQueue == null) {
myRequestQueue = Volley.newRequestQueue(this);
}
// Add the request to the queue...
myRequestQueue.add(documentRequest);
// ... and wait for the document.
// NOTA: User experience can be a concern here. We shouldn't freeze the app...
cdl.await();
return doc[0];
}
I totally agree with the above answer. You can follow any of the below tutorials for fetching data from server
http://www.androidhive.info/2014/05/android-working-with-volley-library-1/
http://www.vogella.com/tutorials/Retrofit/article.html
These two are the best libraries for Network calls in android
Before the return statement add a downloadThread.join(). This will wait until the thread has finished and put the response into doc. But: Doing so you will loose all benefit from the asynchronous execution, it's behaving the same as you just would code:
public String pare(final String url){
return Jsoup.connect(url).get().toString();
}

Android Volley: Static vs Object

I am a junior android developer and I almost finished the alpha version of my first big project. I think that I have good knowledge of java but I am not sure if I organized my app right.
Short description: I use in my app the volley library to send and receive data from server. Because of that I created a class to manage server methods. In that class I created a lot of static methods for every connection to server I need(like this example):
public static void sendDataToServer(final Context context, final String data) {
StringRequest mStringRequest = new StringRequest(Request.Method.POST, URL_VERIFY, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// get response
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// get error response
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
// the POST parameters:
params.put(API_KEY, API_KEY_VALUE);
params.put(API_KEY_DATA, data);
return params;
}
};
Volley.newRequestQueue(context).add(mStringRequest);
}
So in my activities I call this like MyServerClass.sendDataToServer(...)
My question is: Is it ok to call my server methods like that? Or should I make them instance methods and instantiate MyServerClass when activity is started? I must mention that I have about 5 methods in that class.
I have another class like that with methods to check data accuracy. Should I also make them instance methods and instantiate it in the activities I need?
Any reference or advice is welcome. Thanks in advance!
No, in your case, both ways will have the same result...
The only thing to mention is, that if you need to receive the response to your request too (may be in the future), you will need to add a Delegate / Callback / Interface to your class, to get the result right back to your calling activity instance... In that case it would be better to create a "non-static instance method" way... But you can add a non-static Method to your Class too so I don't see anything against it.
UPDATE TO COMMENT
Well for example, if you want to provide a ListView with Images... In most cases you first request an JSONArray with your ListView entries, which contains the links to Bitmaps located on the remote Server...
If you download Images Async and put them into the ImageViews in the rows of a ListView (while the user scrolls), it could be possible that images are loaded longer and the ListView will show images in wrong places... For something like that you will need a Singleton Pattern, which will manage the downloads for you... This will not be possible with your class/static Method
Although this question has already had an accepted answer, however, I'd like to share my code that looks like your issue. Hope this helps!
I also use Interface like #Neo answer, as the following:
public interface VolleyResponseListener {
void onError(String message);
void onResponse(Object response);
}
Then in my VolleyUtils class:
public static void makeJsonObjectRequest(Context context, String url, final VolleyResponseListener listener) {
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
(url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
listener.onResponse(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
listener.onError(error.toString());
}
}) {
#Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers, PROTOCOL_CHARSET));
return Response.success(new JSONObject(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JSONException je) {
return Response.error(new ParseError(je));
}
}
};
// Access the RequestQueue through singleton class.
VolleySingleton.getInstance(context).addToRequestQueue(jsonObjectRequest);
}
Then in Activity:
VolleyUtils.makeJsonObjectRequest(mContext, url, new VolleyResponseListener() {
#Override
public void onError(String message) {
}
#Override
public void onResponse(Object response) {
}
});
P/S: my project uses Google's official Volley library, instead of using compile 'com.mcxiaoke.volley:library:1.0.17' in build.gradle. As a result, JsonObjectRequest(...) will have a difference at its definition.

Categories

Resources