I want to add each user response to my list listItem, inserting the response's specific key and value pair. However, in this code, the first loop of getCat() executes 4 times ... then all responses get added to the last key those are 4.
public void getCat(){
String url = "http://******/*****/*****.json";
HashMap<String, List<CatType> hmap=new HashMap<String, ArrayList<CatType>>();
private List<ListItem> listItems;
for(int i=1;i<5;i++)
{
JsonObjectRequest jsonReq = new JsonObjectRequest(Method.GET,
url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d(TAG, "Response: " + response.toString());
parseJsonFeed(response);
listItems = new ArrayList<ListItem>();
listItem.addAll(O_listItems);
hmap.put("["+i+"]",listItem);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "Error: " + error.getMessage());
}
});
// Adding request to volley request queue
AppController.getInstance().addToRequestQueue(jsonReq);
}
}
private void parseJsonFeed(JSONObject response) {
try {
JSONArray feedArray = response.getJSONArray("food");
for (int i = 0; i < feedArray.length(); i++) {
JSONObject feedObj = (JSONObject) feedArray.get(i);
OrderListItem item=new OrderListItem();
item.setId(feedObj.getInt("id"));
item.setImage(feedObj.getString("image"));
item.setItem_name(feedObj.getString("name"));
O_listItems.add(item);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
This is happening because each time you make a request a new thread is created, so before the response comes back from the first hit, a new hit is made and this goes on. For such kind of situation it is better to use AsyncTask or make synchronous hits. See this answer for making synchronous hits.
Related
I have a simple URL that fetches some pics from pixabay website. with this URL: https://pixabay.com/api/?key=15507399-305bf88eb0892f7cdf58fb66b&image_type=photo&pretty=true&q=yellow+flowers.
Clicking on the link it is shown the JSON response. I want to get the "id" and "largeImageURL". but the method doesn't even execute. the Arraylist that is supposed to contain the values is always size = 0.
I have added the
<uses-permission android:name="android.permission.INTERNET"/>
I have no clue what I'm missing here
requestQueue = Volley.newRequestQueue(this);
loadImages();
//testing
String[] names = null;
for (int i = 0; i < images.size(); i++) {
names[i] = images.get(i).getId();
}
}
private void loadImages() {
String url = "https://pixabay.com/api/?key=15507399-305bf88eb0892f7cdf58fb66b&image_type=photo&pretty=true&q=yellow+flowers";
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray hits = response.getJSONArray("hits");
for (int i = 0; i < hits.length(); i++) {
JSONObject pics = hits.getJSONObject(i);
images.add(new Flowers(pics.getString("id"), pics.getString("largeImageURL")));
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(MainActivity.this, "ha", Toast.LENGTH_SHORT).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("test", "Error", error);
}
});
requestQueue.add(request);
}
Your code is working except that the placement of the block of codes '//testing' is at the wrong location resulting in size = 0. It takes time for the data to come in before 'onResponse()' get triggered and stores the data in 'images'. But you are already accessing the 'images' before 'onResponse()'.
The jason array request code goes like this:
JsonArrayRequest arrayRequest = new JsonArrayRequest(Request.Method.GET,url, (JSONArray) null , new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
try {
Log.d("Response:", String.valueOf(response.getJSONObject(0)));
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(context, "Response not recieved", Toast.LENGTH_SHORT).show();
}
});
And I've used a singleton instance of a request queue, to fetch the data,
AppController.getInstance(context.getApplicationContext()).addToRequestQueue(arrayRequest);
I'm using an api service that supplies a bunch of questions (The api generates a url, which returns a collection of JSON Objects, An Array (Just try and Open the url link, the json array will be seen)
But when I run the app, the request is not even getting a response,the progam flow is going into the error listner block.
Can someone explain this behaviour? Is it because the JSON array supplied by the url, has nested arrays? Why?
I tried reading and anlyzing other questions here, which might have the same issue, But i found nothing.
You want to just change JsonArrayRequest to JsonObjectRequest:
Please copy and paste below code:
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET,
url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d("TAG", response.toString());
try {
JSONArray jsonArray = response.getJSONArray("results");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
String category = jsonObject.getString("category");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("TAG", "Error: " + error.getMessage());
// hide the progress dialog
}
});
AppController.getInstance().addToRequestQueue(jsonObjReq, "TAG");
Follow this link for learn other request: Androidhive
I have using volley library for fetching data. I used a HashMap to store response data. When I fetch the data out of the volley request it is showing empty. I knew I should use this Hashmap inside the response method. But I need to get that in a global variable. Any suggestions?
String liveURL = BASE_URL + "livescores?api_token=" + API_KEY;
HashMap<String, String> hashMap = new HashMap<>();
JsonObjectRequest livescoresRequest = new JsonObjectRequest(Request.Method.GET,
liveURL, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
final JSONArray liveArray = response.getJSONArray("data");
for (int i = 0; i < liveArray.length(); i++) {
JSONObject data = liveArray.getJSONObject(i);
String liveID = data.getString("id");
final String league_id = data.getString("league_id");
hashMap.put(league_id, liveID);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("Error", error.toString());
}
});
Volley.newRequestQueue(getContext()).add(livescoresRequest);
Log.i("HASHMAP", hashMap.toString());
I am working on an android app.
I want to retrieve json data into an ArrayList of my data model called Expert.
Here is the code on the onCreate() method
mExpertsList = new ArrayList<Expert>();
loadData();
Log.v("RESPONSE", Integer.toString(mExpertsList.size()));
Here is the code in the function retrieving json data.
private void loadData(){
RequestQueue queue = Volley.newRequestQueue(MainActivity.this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, "http://microblogging.wingnity.com/JSONParsingTutorial/jsonActors",
null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jarray = response.getJSONArray("actors");
for (int i = 0; i < jarray.length(); i++) {
JSONObject object = jarray.getJSONObject(i);
Expert expert = new Expert();
expert.setImageUrl(object.getString("image"));
expert.setName(object.getString("name"));
expert.setTopic(object.getString("country"));
expert.setRating(random.nextFloat() * ((maxRating - minRating) + minRating));
expert.setDescription(object.getString("description"));
mExpertsList.add(expert);
}
}
catch(JSONException e){
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
queue.add(jsonObjectRequest);
}
Inside loadData() method the mExpertsList shows size of 6 at end of for loop. Checked this using log messages.
But a Log statement immediately after loadData() shows that mExpertsList has size of zero.
What am I missing here?
JsonObjectRequest is an Asynchronous request so your list will be update on other thread . And you logged the size synchronously so it will print 0 always .
Access the List inside onResponse(JSONObject response);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, "http://microblogging.wingnity.com/JSONParsingTutorial/jsonActors",
null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jarray = response.getJSONArray("actors");
for (int i = 0; i < jarray.length(); i++) {
JSONObject object = jarray.getJSONObject(i);
Expert expert = new Expert();
expert.setImageUrl(object.getString("image"));
expert.setName(object.getString("name"));
expert.setTopic(object.getString("country"));
expert.setRating(random.nextFloat() * ((maxRating - minRating) + minRating));
expert.setDescription(object.getString("description"));
mExpertsList.add(expert);
}
Log.v("RESPONSE", mExpertsList.size());
}
catch(JSONException e){
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
mExpertsList = new ArrayList<Expert>(); // You are initializing your list with size 0
loadData(); // Calling the API which will run in background
So whenever you are calling
Log.v("RESPONSE", Integer.toString(mExpertsList.size()));just after loadData() method your mExpertsList is still of size 0.
Size will change only after you get your API response.
This is an Asynchronous operation, Volley will not wait for your response and execute your next code.
If you want to print Arraylist size then print it just after for loop,
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, "http://microblogging.wingnity.com/JSONParsingTutorial/jsonActors",
null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jarray = response.getJSONArray("actors");
for (int i = 0; i < jarray.length(); i++) {
JSONObject object = jarray.getJSONObject(i);
Expert expert = new Expert();
expert.setImageUrl(object.getString("image"));
expert.setName(object.getString("name"));
expert.setTopic(object.getString("country"));
expert.setRating(random.nextFloat() * ((maxRating - minRating) + minRating));
expert.setDescription(object.getString("description"));
mExpertsList.add(expert);
}
Log.v("RESPONSE", mExpertsList.size());
}
catch(JSONException e){
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
It will print the exxact size of your list.
It looks like you are making some kind of asynchronous call when you call loadData():
mExpertsList = new ArrayList<Expert>();
loadData();
Log.v("RESPONSE", Integer.toString(mExpertsList.size()));
When you check the size, it is possible that onResponse(), the handler for the web call, has not yet been called. If so, then the size would still appear to be zero.
You should only be relying on the contents of mExpertsList being there if onResponse has been successfully called with actual content.
Do this change in part 1:
mExpertsList = new ArrayList<Expert>();
loadData();
//Log.v("RESPONSE", Integer.toString(mExpertsList.size()));----Comment it out
Change in part 2:
private void loadData(){
RequestQueue queue = Volley.newRequestQueue(MainActivity.this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, "http://microblogging.wingnity.com/JSONParsingTutorial/jsonActors",
null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jarray = response.getJSONArray("actors");
for (int i = 0; i < jarray.length(); i++) {
JSONObject object = jarray.getJSONObject(i);
Expert expert = new Expert();
expert.setImageUrl(object.getString("image"));
expert.setName(object.getString("name"));
expert.setTopic(object.getString("country"));
expert.setRating(random.nextFloat() * ((maxRating - minRating) + minRating));
expert.setDescription(object.getString("description"));
mExpertsList.add(expert);
Log.v("RESPONSE", Integer.toString(mExpertsList.size())); //-----New ADDED
}
}
catch(JSONException e){
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
queue.add(jsonObjectRequest);
}
I Know at first glance it's known mistake made by beginners but:
My standard response looks like this:
public ArrayList<Beer> jsonResponse(){
beerList.clear();
requestQueue = Volley.newRequestQueue(this);
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(
Request.Method.GET,
Constants.BASE_API_URL + Constants.BEER_LIST_URL_ENDPOINT,
null,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
try {
for (int i = 0; i < response.length(); i++) {
JSONObject beerJsonObject = response.getJSONObject(i);
System.out.println(response.toString());
Beer beer = new Beer();
if (beerJsonObject.has("yeast")) {
beer.setYeast(beerJsonObject.getString("yeast"));
}
beer.setName(beerJsonObject.getString("name"));
beer.setIbu(beerJsonObject.getString("ibu"));
beer.setAlc(beerJsonObject.getString("abv"));
beer.setImgUrl(beerJsonObject.getString("image_url"));
beer.setId(beerJsonObject.getString("id"));
beer.setDescription(beerJsonObject.getString("description"));
beer.setFoodPairing(beerJsonObject.getString("food_pairing"));
beer.setFirstBrewed(beerJsonObject.getString("first_brewed"));
System.out.println(beer.getName()+" "+beer.getIbu()+" "+beer.getImgUrl());
beerList.add(beer);
}
beerRecyclerViewAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, "Error", Toast.LENGTH_SHORT).show();
}
}
);
// Add JsonArrayRequest to the RequestQueue
requestQueue.add(jsonArrayRequest);
return beerList;
}
Everything works except "yeast" item:
if (beerJsonObject.has("yeast")) {
beer.setYeast(beerJsonObject.getString("yeast"));
}
without that if statement I've got standard json err. response no value for "yeast", I thought maybe not every object in response has this value and added that. But that doesn't helped, I still can't get that value, like it wouldn't exist in array, but it's not true, even in System.out.println(response.toString()) I can see a lot of "yeast" .
Here is example response from API I'm working with: https://api.punkapi.com/v2/beers
yeast is under ingredients
so should be:
if (beerJsonObject.has("ingredients")) {
JSONObject ingredients = beerJsonObject.getJSONObject("ingredients");
if (ingredients.has("yeast")) {
beer.setYeast(ingredients.getString("yeast"));
}
}