Show response everytime when hitting the api in volley
Asked Answered
S

6

6

I need to get the response 8 times nearly(dynamic) based on the array list size.So I had used for loop.inside the for loop, I am using volley get response.

While hitting the api everytime,I need to get the onResponse.

Below I have posted the logcat and relevant code:

Logcat: (Edited)

 E/getAvaArrStr: 
 E/urlAva: 

 E/getAvaArrStr: 
 E/urlAva: 

 E/getAvaArrStr: 
 E/urlAva: 

 E/getAvaArrStr: 
 E/urlAva: 

 E/getAvaArrStr: 
 E/urlAva:

 /* Response */

 E/ResponseAvatar: 
 E/url: 
 E/CheckArrBit: 

 E/ResponseAvatar: 
 E/url: 
 E/CheckArrBit: 

 E/ResponseAvatar: 
 E/url: 
 E/CheckArrBit: 

 E/ResponseAvatar: 
 E/url: 
 E/CheckArrBit: 

CardsFragment.java: (Edited)

RequestQueue queue = Volley.newRequestQueue(getActivity());

for (int i = 0; i < alAvaArr.size(); i++) {

    getAvaArrStr = alAvaArr.get(i);

    Log.e("getAvaArrStr", "" + getAvaArrStr);

    urlAva = BurblrUtils.BR_AVATAR_IMAGE + getAvaArrStr + "&android=1";

    Log.e("urlAva", urlAva);


    requestAva = new StringRequest(Request.Method.GET, urlAva, new Response.Listener<String>() {

        @Override
        public void onResponse(String response) {
            if (response != null && !response.startsWith("<HTML>")) {
                Log.e("ResponseAvatar", response);

                dialog.dismiss();

                try {

                    Toast.makeText(getActivity(), "Running ", Toast.LENGTH_SHORT).show();

                    String url = response.replace("\\", "");
                    url = url.replace("\"", "");

                    Log.e("url", url);

                    arrBitMap.add(url);

                    Log.e("CheckArrBit", "" + arrBitMap);

                    //     Glide.with(getActivity()).load(url).placeholder(R.drawable.ic_launcher).error(R.drawable.ic_launcher).into(img);


                    getSwipeImage();

                    myAppAdapter.notifyDataSetChanged();

                } catch (Exception e) {
                    e.printStackTrace();
                    dialog.dismiss();
                }

            } else {
                dialog.dismiss();
            }
        }
    }, new Response.ErrorListener() {

        @Override
        public void onErrorResponse(VolleyError error) {
            if (error != null) {
                Log.e("error", error.toString());
                dialog.dismiss();
            }

        }
    }) {
        @Override
        protected Map<String, String> getParams() {
            Map<String, String> params = new HashMap<String, String>();

            params.put("file", getAvaArrStr);

            Log.e("paramsImg", "" + params);

            Log.e("RunningParams", "Testing");


            return params;
        }

        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            Map<String, String> params = new HashMap<String, String>();
            params.put("Content-Type", "application/x-www-form-urlencoded");
            return params;
        }
    };

       queue.add(requestAva);

        queue.getCache().remove(urlAva);

}

Expected Log Response Sequence:

E/getAvaArrStr: -> E/urlAva: -> E/ResponseAvatar: -> E/url: -> E/CheckArrBit:

I need to get the response everytime on running the loop.That means nearly 8 times, based on the arrayList size, I have to get the response message,is it possible in volley? any suggestion to overcome this issue.

Shill answered 25/3, 2016 at 6:18 Comment(0)
A
1

You must create a function. The function makeRequest handles your next Api call

public class MainActivity extends AppCompatActivity {

    RequestQueue queue;
    int mIndex = 0 ;
    ArrayList<String> alAvaArr;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mQueue = Volley.newRequestQueue(getActivity());
        alAvaArr = ///////// initialize here

        mIndex  = 0;
        makeRequest(alAvaArr.get(mIndex));
    }

    public void makeRequest( String arg){



        getAvaArrStr = arg;

        Log.e("getAvaArrStr", "" + getAvaArrStr);

        urlAva = BurblrUtils.BR_AVATAR_IMAGE + getAvaArrStr + "&android=1";

        Log.e("urlAva", urlAva);


        requestAva = new StringRequest(Request.Method.GET, urlAva, new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {
                if (response != null && !response.startsWith("<HTML>")) {
                    Log.e("ResponseAvatar", response);

                    dialog.dismiss();

                    try {

                        Toast.makeText(getActivity(), "Running ", Toast.LENGTH_SHORT).show();

                        String url = response.replace("\\", "");
                        url = url.replace("\"", "");

                        Log.e("url", url);

                        arrBitMap.add(url);

                        Log.e("CheckArrBit", "" + arrBitMap);

                        //     Glide.with(getActivity()).load(url).placeholder(R.drawable.ic_launcher).error(R.drawable.ic_launcher).into(img);


                        getSwipeImage();

                        myAppAdapter.notifyDataSetChanged();

                        mIndex++;
                        if(mIndex < alAvaArr.size()){
                            makeRequest(alAvaArr.get(mIndex));
                        } 

                    } catch (Exception e) {
                        e.printStackTrace();
                        dialog.dismiss();
                    }

                } else {
                    dialog.dismiss();
                }
            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                if (error != null) {
                    Log.e("error", error.toString());
                    dialog.dismiss();
                }

            }
        }) {
            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<String, String>();

                params.put("file", getAvaArrStr);

                Log.e("paramsImg", "" + params);

                Log.e("RunningParams", "Testing");


                return params;
            }

            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                Map<String, String> params = new HashMap<String, String>();
                params.put("Content-Type", "application/x-www-form-urlencoded");
                return params;
            }
        };

        mQueue.add(requestAva);

 }
Ambivert answered 2/4, 2016 at 14:12 Comment(4)
No he can call makeRequest from onErrorResponse and catch block and also it depends on his policy, maybe he wants to break the whole process and tell there is an error in network or ...Ambivert
This answer working perfectly what I am expected.Thank you very much MML.Shill
@Naruto: another option if you don't want to re-initlialize the requests (I mean by calling requestAva = new StringRequest): your project should use Google's Volley as a module (not Jar file, not Macxiaoke lib), then you update Request.java (adding setUrl(...) method), create public class MyRequest extends Request<NetworkResponse>, then you can use, for example, if (num < ...){ num++; url = baseUrl + num; myRequest.setUrl(url); requestQueue.add(myRequest); } :)Steep
@Steep I will try this one also :)Shill
A
2

You are creating the RequestQueue inside the for loop...

So there is no Call Queue...Move it out of the for loop

RequestQueue queue = Volley.newRequestQueue(getActivity());
for(..){
   ...
   queue.add(requestAva);
}
Alloy answered 25/3, 2016 at 6:46 Comment(10)
if you moved the RequestQueue out of the loop then update your question code pleaseAlloy
thank you for your answer.Let me check it carefully and tell youShill
I have posted edited logcat and cardsFragment class.Can you please check it. I am getting response several times.But only one issue.The LOG sequence have to be E/getAvaArrStr: -> E/urlAva: -> E/ResponseAvatar: -> E/url: -> E/CheckArrBit: like this.But In my edited logcat the first two log sequence continuouly loading eight times.then response running eight times.thats the only issue.Shill
Hi @Naruto, That's because the requests are run in a different thread than the main thread. So, there's nothing wrong in getting that sort of Log! ie: First all of your code related to creating the requests are run. Then eventually you'll get responses when the relevant threads execute!Micheal
Thank you for this answer.it helped meShill
@RuchiraRandana now I understood.Shill
@Naruto glad i could help (-:Alloy
@Alloy I am not getting the right image for right title position.images taking wrong position for every title.Because LOG sequence have to be E/getAvaArrStr: -> E/urlAva: -> E/ResponseAvatar: -> E/url: -> E/CheckArrBit: like this.But In my edited logcat the first two log sequence continuouly loading eight times.then response running eight times.thats the only issue.Any suggestion.Shill
Hi @Naruto can you please elaborate. I didn't really understand what you meant. btw change this urlAva = BurblrUtils.BR_AVATAR_IMAGE + getAvaArrStr + "&android=1"; to String urlAva = BurblrUtils.BR_AVATAR_IMAGE + getAvaArrStr + "&android=1";Alloy
Also if you want sychro writing you should add data to the Queue using the Response method, but it will be much slower..Also requestAva to Request requestAvaAlloy
S
2

Because Volley is asynchronous, so IMO, you should not put the requests inside for-loop like the code in your question. Please refer to the following sample code then apply its logic to your app. Hope it helps!

public class MainActivity extends AppCompatActivity {
    private int num = 0;
    private JsonArrayRequest jsonArrayRequest;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final RequestQueue requestQueue = Volley.newRequestQueue(this);
        String url = "http://...";
        jsonArrayRequest = new JsonArrayRequest(url, new Response.Listener<JSONArray>() {
            @Override
            public void onResponse(JSONArray response) {
                Log.i("Num", String.valueOf(num));
                Log.i("Response", response.toString());
                if (num < 8) {
                    num++;
                    requestQueue.add(jsonArrayRequest);
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e("Error", error.toString());
            }
        });
        num++;
        requestQueue.add(jsonArrayRequest);
    }
}

Logcat output as below:

03-28 13:14:29.885 13262-13262/com.example.googlevolley I/Num: 1
03-28 13:14:29.885 13262-13262/com.example.googlevolley I/Response: [{"id":"1","name":"Information Technology"},{"id":"2","name":"Human Resources"},{"id":"3","name":"Marketing and PR"},{"id":"4","name":"Research and Developement"}]
03-28 13:14:29.935 13262-13262/com.example.googlevolley I/Num: 2
03-28 13:14:29.955 13262-13262/com.example.googlevolley I/Response: [{"id":"1","name":"Information Technology"},{"id":"2","name":"Human Resources"},{"id":"3","name":"Marketing and PR"},{"id":"4","name":"Research and Developement"}]
03-28 13:14:30.085 13262-13262/com.example.googlevolley I/Num: 3
03-28 13:14:30.085 13262-13262/com.example.googlevolley I/Response: [{"id":"1","name":"Information Technology"},{"id":"2","name":"Human Resources"},{"id":"3","name":"Marketing and PR"},{"id":"4","name":"Research and Developement"}]
03-28 13:14:30.245 13262-13262/com.example.googlevolley I/Num: 4
03-28 13:14:30.245 13262-13262/com.example.googlevolley I/Response: [{"id":"1","name":"Information Technology"},{"id":"2","name":"Human Resources"},{"id":"3","name":"Marketing and PR"},{"id":"4","name":"Research and Developement"}]
03-28 13:14:30.266 13262-13262/com.example.googlevolley I/Num: 5
03-28 13:14:30.266 13262-13262/com.example.googlevolley I/Response: [{"id":"1","name":"Information Technology"},{"id":"2","name":"Human Resources"},{"id":"3","name":"Marketing and PR"},{"id":"4","name":"Research and Developement"}]
03-28 13:14:30.296 13262-13262/com.example.googlevolley I/Num: 6
03-28 13:14:30.296 13262-13262/com.example.googlevolley I/Response: [{"id":"1","name":"Information Technology"},{"id":"2","name":"Human Resources"},{"id":"3","name":"Marketing and PR"},{"id":"4","name":"Research and Developement"}]
03-28 13:14:30.306 13262-13262/com.example.googlevolley I/Num: 7
03-28 13:14:30.306 13262-13262/com.example.googlevolley I/Response: [{"id":"1","name":"Information Technology"},{"id":"2","name":"Human Resources"},{"id":"3","name":"Marketing and PR"},{"id":"4","name":"Research and Developement"}]
03-28 13:14:30.316 13262-13262/com.example.googlevolley I/Num: 8
03-28 13:14:30.316 13262-13262/com.example.googlevolley I/Response: [{"id":"1","name":"Information Technology"},{"id":"2","name":"Human Resources"},{"id":"3","name":"Marketing and PR"},{"id":"4","name":"Research and Developement"}]
Steep answered 28/3, 2016 at 6:19 Comment(4)
Hi@Steep Very Simple but why did you manually specified the value. More useful if it is dynamicSusceptive
@I_Droid thanks for your comment. I agree with you. However, as I said to the OP before, his and my comments deleted :), I just told him the logic that he should not put the requests inside for-loop as in his question. Now, he can check if (num < alAvaArr.size()) instead of if (num < 8), and change the UrlsSteep
@Steep I am checking this solution.But one problem occurred to me.I am using this code : for (int i = 0; i < alAvaArr.size(); i++) { getAvaArrStr = alAvaArr.get(i); That means getAvaArrStr is the urlString I need to pass it to the response everytime based on the alAvaArrSize(). So In outside JsonArrayRequest, I can't hit the api nearly 8 or more times based on the arraylist size.Because in your code you used if loop inside onResponse() methodShill
You can try the solution of @MML13Steep
A
1

You must create a function. The function makeRequest handles your next Api call

public class MainActivity extends AppCompatActivity {

    RequestQueue queue;
    int mIndex = 0 ;
    ArrayList<String> alAvaArr;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mQueue = Volley.newRequestQueue(getActivity());
        alAvaArr = ///////// initialize here

        mIndex  = 0;
        makeRequest(alAvaArr.get(mIndex));
    }

    public void makeRequest( String arg){



        getAvaArrStr = arg;

        Log.e("getAvaArrStr", "" + getAvaArrStr);

        urlAva = BurblrUtils.BR_AVATAR_IMAGE + getAvaArrStr + "&android=1";

        Log.e("urlAva", urlAva);


        requestAva = new StringRequest(Request.Method.GET, urlAva, new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {
                if (response != null && !response.startsWith("<HTML>")) {
                    Log.e("ResponseAvatar", response);

                    dialog.dismiss();

                    try {

                        Toast.makeText(getActivity(), "Running ", Toast.LENGTH_SHORT).show();

                        String url = response.replace("\\", "");
                        url = url.replace("\"", "");

                        Log.e("url", url);

                        arrBitMap.add(url);

                        Log.e("CheckArrBit", "" + arrBitMap);

                        //     Glide.with(getActivity()).load(url).placeholder(R.drawable.ic_launcher).error(R.drawable.ic_launcher).into(img);


                        getSwipeImage();

                        myAppAdapter.notifyDataSetChanged();

                        mIndex++;
                        if(mIndex < alAvaArr.size()){
                            makeRequest(alAvaArr.get(mIndex));
                        } 

                    } catch (Exception e) {
                        e.printStackTrace();
                        dialog.dismiss();
                    }

                } else {
                    dialog.dismiss();
                }
            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                if (error != null) {
                    Log.e("error", error.toString());
                    dialog.dismiss();
                }

            }
        }) {
            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<String, String>();

                params.put("file", getAvaArrStr);

                Log.e("paramsImg", "" + params);

                Log.e("RunningParams", "Testing");


                return params;
            }

            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                Map<String, String> params = new HashMap<String, String>();
                params.put("Content-Type", "application/x-www-form-urlencoded");
                return params;
            }
        };

        mQueue.add(requestAva);

 }
Ambivert answered 2/4, 2016 at 14:12 Comment(4)
No he can call makeRequest from onErrorResponse and catch block and also it depends on his policy, maybe he wants to break the whole process and tell there is an error in network or ...Ambivert
This answer working perfectly what I am expected.Thank you very much MML.Shill
@Naruto: another option if you don't want to re-initlialize the requests (I mean by calling requestAva = new StringRequest): your project should use Google's Volley as a module (not Jar file, not Macxiaoke lib), then you update Request.java (adding setUrl(...) method), create public class MyRequest extends Request<NetworkResponse>, then you can use, for example, if (num < ...){ num++; url = baseUrl + num; myRequest.setUrl(url); requestQueue.add(myRequest); } :)Steep
@Steep I will try this one also :)Shill
R
1

I will add another option triggered by the words of BNK

Because Volley is asynchronous...

Here we have 2 kind of solutions essentially doing synchronization of your requests.

1) solution to sync requests by triggering them from within the response callback of the previous one (request chaining)

2) my solution using Futures to sync the calls thus converting them in blocking calls (one wait for the previous one to finish).

they both work and will execute almost with the same speed.

however they all work against the multithreading advantage of Volley.

If your only goal is to link the URLs you provide first with the responses then you can simply have MAP and put them in the right place when response is received.

in this example i will use Map (urlAndResponses) to combine your 2 Collections

alAvaArr and arrBitMap

so basically instead of this :

for (int i = 0; i < alAvaArr.size(); i++) {

    getAvaArrStr = alAvaArr.get(i);

you put:

 final Map<String, String> urlAndResponses = Collections.synchronizedMap(new HashMap<String, String>());
            for (Map.Entry<String, String> entry:urlAndResponses.entrySet()) {
               final String getAvaArrStr = entry.getKey();

then in your callback instead of :

arrBitMap.add(url);

you put:

urlAndResponses.put(getAvaArrStr, url);

This way you will not have the logs as you want but you will have the response in the right place at any moment and still all the requests will run asynchronously.

Recidivate answered 2/4, 2016 at 23:15 Comment(0)
C
0

To run the volley requests multiple times (like in a for loop) with your log output strictly following the order that you have defined you could do this-

1)put the code you have in the 'for loop' inside a runnable

Runnable runnable=new Runnable(){
    //your code here
};

2)Create a Handler anywhere before the above code using

Handler handler=new Handler();

and now put this line as the last line inside onResponse

handler.post(runnable);

3) Now your code will run in an infinite loop so you need to create an exit condition. you could create a counter variable and increment it inside onResponse. Then just put handler.post() inside a if condition checking if counter<8 or something similar.

Using a handler you can make the volley request again without incrementing the counter from onErrorResponse and can better handle request failure than using a for loop.

Also your exit condition can be some boolean you get as a response and therefore you can let the server tell you how many requests to make instead of a hardcoded fixed number.

Thirdly (and as i have mentioned before) the code that you have in the runnable before you make volley request will always be executed after the previous request is completed so you can make use of this strict ordering if you so wish.

If you have any doubts or some of the code doesnt work kindly comment so i can make the required edits.

Compendium answered 28/3, 2016 at 5:14 Comment(1)
for (int i = 0; i < alAvaArr.size(); i++) { getAvaArrStr = alAvaArr.get(i);.That means getAvaArrStr is the urlString I need to pass it to the response everytime based on the alAvaArrSize(). So In outside JsonArrayRequest, I can't hit the api nearly 8 or more times based on the arraylist size.Because in your code you used if loop inside onResponse() methodShill
R
0

From your requirements i suppose you need synchronous execution. So ill advise to use futures. It is also important to note that in order not to block the main thread you have execute the whole loop on a separate thread. ex:

new Thread(new Runnable() {
                @Override
                public void run() {
..your loop...
 }
            }).start();

when you create your request:

requestAva = new StringRequest(Request.Method.GET, urlAva, new Response.Listener<String>() {

        @Override
        public void onResponse(String response) {
            if (response != null && !response.startsWith("<HTML>")) {
                Log.e("ResponseAvatar", response);

                dialog.dismiss();

                try {

                    Toast.makeText(getActivity(), "Running ", Toast.LENGTH_SHORT).show();

                    String url = response.replace("\\", "");
                    url = url.replace("\"", "");

                    Log.e("url", url);

                    arrBitMap.add(url);

                    Log.e("CheckArrBit", "" + arrBitMap);

                    //     Glide.with(getActivity()).load(url).placeholder(R.drawable.ic_launcher).error(R.drawable.ic_launcher).into(img);


                    getSwipeImage();

                    myAppAdapter.notifyDataSetChanged();

                } catch (Exception e) {
                    e.printStackTrace();
                    dialog.dismiss();
                }

            } else {
                dialog.dismiss();
            }
        }
    }, new Response.ErrorListener() {

        @Override
        public void onErrorResponse(VolleyError error) {
            if (error != null) {
                Log.e("error", error.toString());
                dialog.dismiss();
            }

        }
    })

change to this:

RequestFuture<String> future = RequestFuture.newFuture() {
 @Override
    public synchronized void onResponse(String response) {
 if (response != null && !response.startsWith("<HTML>")) {
                Log.e("ResponseAvatar", response);

                dialog.dismiss();

                try {

                    Toast.makeText(getActivity(), "Running ", Toast.LENGTH_SHORT).show();

                    String url = response.replace("\\", "");
                    url = url.replace("\"", "");

                    Log.e("url", url);

                    arrBitMap.add(url);

                    Log.e("CheckArrBit", "" + arrBitMap);

                    //     Glide.with(getActivity()).load(url).placeholder(R.drawable.ic_launcher).error(R.drawable.ic_launcher).into(img);


                    getSwipeImage();

                    myAppAdapter.notifyDataSetChanged();

                } catch (Exception e) {
                    e.printStackTrace();
                    dialog.dismiss();
                }

            } else {
                dialog.dismiss();
            }
       super.onResponse(response);
    }
    @Override
    public synchronized void onErrorResponse(VolleyError error) {
       if (error != null) {
                Log.e("error", error.toString());
                dialog.dismiss();
            }
        super.onErrorResponse(error);
    }
};
 requestAva = new StringRequest(Request.Method.GET, urlAva, future, future) {...

note like this you put as listeners your Future and your previous listeners are not implemented in your Future. then when you add the request

 queue.add(requestAva);

change to :

queue.add(requestAva);

  try {
    future.get();
    // the response is handled by your Future synchroniously
  } catch (InterruptedException e) {
    // handle the error
  } catch (ExecutionException e) {
    // handle the error
  }
Recidivate answered 2/4, 2016 at 14:32 Comment(7)
One point about your solution: you have to create another thread to call future.get() because it is synchronous then when you want to update UI have to go back to main thread then again background thread to call future.get() and again... but volley has already done that for us.Ambivert
the purpose to use future is get the thing in sync as this is what is expectedRecidivate
Yes but in the world of android things are a bit different. can we call network on main thread? can we update UI from background thread?Ambivert
i think you mean for the whole loop. yes it must be spawned to a new thread yes. but the whole think ensures we get the requests in sync and all of themRecidivate
well ... it seems that you are confused how threads, volley and futures work .Recidivate
future.get(); is a blocking operation, I think you have to search and read more. Anyway let him try and see the results :-)Ambivert
again this is what is expected from the future. the code works and its tested. i suggest you to take a look at android.googlesource.com/platform/frameworks/volley/+/master/… . I also kindly ask you to stop this discussion here if you have questions or difficulties with volley send me mail [email protected]. you can also try github.com/apptik/jus :)Recidivate

© 2022 - 2024 — McMap. All rights reserved.