I have to make several requests to an API for an Android App and I am having the following problem:
I have a list of items and I have to make a request for each in order to get some data and show it in the app. When my list's size is 1 (in case I have only one item), the app works perfectly but if I have more I get the data mixed and one item have the value of other and things like that.
I am using JsonObjectRequest and Volley. I use callback interfaces for sending back the request data to the activities. I think it's probably a synchronisation problem but I'm not sure and I'm a bit frustrated. I've tried everything!
Request Code:
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, urlMarket, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONObject singleResult;
singleResult = response.getJSONArray("result").getJSONObject(0);
coin.setHigh(singleResult.getDouble("High"));
coin.setLow(singleResult.getDouble("Low"));
coin.setLast(singleResult.getDouble("Last"));
coin.setVolInBtc(singleResult.getDouble("BaseVolume"));
coin.setBid(singleResult.getDouble("Bid"));
coin.setAsk(singleResult.getDouble("Ask"));
coin.setPrevDay(singleResult.getString("PrevDay"));
callback.onSuccess(coin);
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
requestQueue.add(request);
Any kind of help would be appreciated!!
PD.: if there's a better way for doing that instead of JsonObjectRequest, please tell me!
Consider either of these two options:
Extend JSONObjectRequest that accepts a id/token field which is returned as part of the Success/Error callback.
Use a final field as an identifier before you make an API call. Assuming you are making these calls in a loop, you can then refer to this final field from your anonymous callbacks to identify the specific Stock. For example, you can use the ISIN, database ID or ticker symbol to identify the response.
Related
I am using volley package to retrieve data from a website(JSON).
Here is my method
private void getEarthquakeList(){
// ...
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(this);
//Earthquake Feeder
String url ="https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/significant_month.geojson";
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d("Response is: ",response);
//Parsing Json
parseJson(response);
final ListView earthquakeListView = (ListView)findViewById(R.id.list);
//Sort the array according to magnitude
earthquakeArrayList.sort((a, b) -> Double.compare(b.getTime(), a.getTime()));
mAdapter = new EarthquakeAdapter(getApplicationContext(), earthquakeArrayList);
earthquakeListView.setAdapter(mAdapter);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("Error",error.getMessage());
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
}
The problem is that right now I am updating the UI inside this method after it returns the response.
These are the lines
//Sort the array according to a date
earthquakeArrayList.sort((a, b) -> Double.compare(b.getTime(), a.getTime()));
mAdapter = new EarthquakeAdapter(getApplicationContext(), earthquakeArrayList);
earthquakeListView.setAdapter(mAdapter);
While I am running in the MainActivity there is no issue, the user opens the app and gets the list of earthquakes.
The issues start when I want to switch to service where I monitor every couple of minutes or when the website content is changing.
So I want my method without updating the UI in it.
The problem is that If I am not updating the UI inside onResponse, the UI thread continues and results in an empty array.
So this array stay empty earthquakeArrayList if I am not doing it inside
public void onResponse(String response)
Ideas how to separate the two, in one hand running the method and fetching the data and on the other hand the main thread will be able to access the data and not finish executing.
Thanks
EG
The recommended solution right now is to use LiveData. LiveData works on the Observer Pattern, so you can have any number of observers to the updated data both in the Service and the Activity but they need to be under the same context. These are a bit advanced topics but a good way to decouple your UI with the data layer. You can go through these two links
Google IO 2018 session on Livedata
Medium Article on LiveData
I have url that has a json Array which contains a large amount of data.
I call the url with volly jsonArrayRequest like this
public void makeJsonArrayReq(){
showProgressDialog();
JsonArrayRequest req = new JsonArrayRequest(Const.URL_IPD_ADMITED,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d("response ================", response.toString());
textView.setText(response.toString());
hideProgressDialog();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("Error", "Error: " + error.getMessage());
textView.setText("Error Occurs ");
hideProgressDialog();
}
});
AppController.getInstance().addToRequestQueue(req, "array");
}
My devise shows progressDialog for some time after that time it hang out the app then after a few minute it shows the response in the texview but it very lengthy process and it same when internet connection off and extract from volley cache. How can I handle the URL in my apps?
You need to change your api a bit to support pagination. There are several pagination techniques available, you have to choose one that suites your case.
In Android you can save the last fetched pageNumber(if that is what your API returns as page identifier) and your api should accept this variable in request (mostly through query params)
http://43.255.22.123:3000/android/mis/get/ipdAdmitPatMd?pageId=1
And in the next request it should update the pageId to 2.
Since the question is too broad hence providing exact code solution is not possible therefore I have explained the concept.
I am trying to get the response from instagram api using volley, but can't get the data. I did't receive any call back methods like onResponse or onErrorResponse. Nothing show up. I Could not see any error.
here is my code.
public String getUserId(String usrName) {
url = TContants.urlBeforeUserId + usrName + TContants.urlAfterUser;
JsonObjectRequest jsonObjReq;
jsonObjReq = new JsonObjectRequest(Method.GET, url,
null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
TagsResponse gsonData = gson.fromJson(response.toString(), TagsResponse.class);
userId = gsonData.data[0].id.toString();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Volley:", "getUserId response error");
}
});
AppController.getInstance().addToRequestQueue(jsonObjReq,
TContants.tag_json_obj);
return userId;
}
url is working fine, I tested it.
When code running JsonObjectRequest creating. but next step it skip the onResponse and onErrorResponse methods. plz help.
The code inside onResponse is not skipped, that's how it's supposed to work, what you are looking at is a Callback.
A very quick and general explanation would be:
this code does not run serially, instead, onResponse in this case is your implementation of an interface provided by the request object, that will be called when the response arrives, this might take several milliseconds to seconds (depending on the server, since this callback is for a network operation).
Read about callback handling (both network, and the simple ones you create with interfaces - and if you haven't yet - read about interfaces), as it is a major part of programming.
ADDITION:
To see when the response does return, I would print all the parameters before sending them to make sure they are sent correctly, and also print the response itself (response.toString() at the beginning of onResponse) and wait a bit to see it after the request is sent.
(don't be alarmed if the print won't contain readable info, it depends on the implementation of the .toString() method, for now it's just an indication that you got a response at all).
I want to send two different requests and handle two different responses in one Activity using Volley library.
My activity implements onResponseListener, so i have only one onResponse method and both responses are handled here. As they are completely same in structure i cant tell which is which.
How can i tell from which request i have received the response so i can handle them differently? Is there a way to "tag" a request or something like that?
I could set some kind of check variable, e.g. boolean firstRequestIsSent when i send the request, and then check it in the onResponse method, but its a pretty ugly solution.
Many thanks
Instead of implementing onResponse as part of the class, you can instantiate a new Response.Listener with the request. This way you will have a separate listener for each request.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener() {
#Override
public void onResponse(String response) {
// individual response here
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// error here
}
});
I've seen answer to both of these questions, however, when I tried to put them together, I couldn't make it work. The problem itself is pretty simple: I want to get a string from one site and use it in a post request. That means I can only make the post request after I've finished parsing the GET request. The main ideas I'm using are these ones:
How to return response header field to main method using Google Volley for HTTP GET request in Android / Java?
Can I do a synchronous request with volley?
However the synchronous request is blocked and doesn't go on, and the first one is Async.
I believe this to be a simple thing to do, but still, I haven't be able to do it...
Thanks for any help!
Why not do something like this:
// send first request
requestQueue.add(firstRequest, null, new Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
// ** code to parse response **
// send second request
requestQueue.add(secondRequest, null, new Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
// ** code to parse response **
}
}, new ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// ** code to handle errors **
}
}));
}
}, new ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// ** code to handle errors **
}
}));