ArrayList size zero despite adding elements - android

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

Related

Volley request doesn't execute and no data are fetched

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()'.

Parsing JSON and displaying in a RecyclerView

Feedback App
String url = "http://www.dohagarage.com/api/v1/sample";
JsonObjectRequest request = new
JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jsonArray = response.getJSONArray("data");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject hit = jsonArray.getJSONObject(i);
String naame = hit.getString("question");
mExampleList.add(new ExampleItem(naame));
} mExampleAdapter = new ExampleAdapter(MainActivity.this, mExampleList);mRecyclerView.setAdapter(mExampleAdapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
mRequestQueue.add(request);
}
This is the code I used to show the questions using json in a RecyclerView. I want show the options in a radio button.
Please provide more code to better understand but i think you didn't set Layout Manager to RecyclerView

Json Array response doesn't see value for item

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

Android global scope String returns null

I have a String declared at a class level.
String eta;
I am passing a url to a method in that same class that will use volley to retrieve distance from one of Google apis. I then assign the response String to my global variable eta. It has the needed value within the method but the global value is null when it is returned. I can't understand this behavior. What am I doing wrong here?
public String getDuration(String url){
RequestQueue queue = Volley.newRequestQueue(this);
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.POST, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
String j = response.getString("rows");
JSONArray rowa = new JSONArray(j);
JSONObject rowobj = rowa.getJSONObject(0);
JSONArray elementsa = rowobj.getJSONArray("elements");
for (int i = 0; i < elementsa.length(); i++) {
JSONObject currentObject = elementsa.getJSONObject(i);
String duration = currentObject.getString("duration_in_traffic");
JSONObject timeObject = new JSONObject(duration);
**eta = timeObject.getString("text"); //eta has the needed value**
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
queue.add(jsObjRequest);
**return eta; //here eta is null**
}
onResponse(JSONObject response) is asynchronous.
You are calling getDuration(String url) and setting a listener that will be called when the network operation ends.
Instead of waiting the listener to be called you are returning the value (that it is not set at the moment) and that's why you get a null value.
Inside onResponse(JSONObject response) you should call the method that needs eta value.
public void getDuration(String url){
RequestQueue queue = Volley.newRequestQueue(this);
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.POST, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
String j = response.getString("rows");
JSONArray rowa = new JSONArray(j);
JSONObject rowobj = rowa.getJSONObject(0);
JSONArray elementsa = rowobj.getJSONArray("elements");
for (int i = 0; i < elementsa.length(); i++) {
JSONObject currentObject = elementsa.getJSONObject(i);
String duration = currentObject.getString("duration_in_traffic");
JSONObject timeObject = new JSONObject(duration);
eta = timeObject.getString("text"); //eta has the needed value**
methodThatUsesValue(eta);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
queue.add(jsObjRequest);
}

How to stop for loop execution until responce come in android

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.

Categories

Resources