Sebastian Zdroana
Sebastian Zdroana

Reputation: 51

How can I slow down API requests?

I'm using a makeServiceCall to get JSON data from TheMovieDB API.

As they don't have a list of movie id's I have to for loop through id's.

String JSONString = httpHandler.makeServiceCall("https://api.themoviedb.org/3/movie/" + 
                                       i + 
                                       "?api_key=" + API_KEY);

i = id

API_KEY = my API key.

As I'm looping through the URL I get IOExceptions for some of the calls.

I/System.out: ID:   152
I/System.out: ID:   160
I/System.out: ID:   165
I/System.out: ID:   168
I/System.out: ID:   171
E/HttpHandler: IOException: https://api.themoviedb.org/3/movie/181?api_key=b692b9da86f1cf0c1b623ea6e2770101
E/HttpHandler: IOException: https://api.themoviedb.org/3/movie/184?api_key=b692b9da86f1cf0c1b623ea6e2770101
E/HttpHandler: IOException: https://api.themoviedb.org/3/movie/185?api_key=b692b9da86f1cf0c1b623ea6e2770101
E/HttpHandler: IOException: https://api.themoviedb.org/3/movie/186?api_key=b692b9da86f1cf0c1b623ea6e2770101
E/HttpHandler: IOException: https://api.themoviedb.org/3/movie/187?api_key=b692b9da86f1cf0c1b623ea6e2770101
E/HttpHandler: IOException: https://api.themoviedb.org/3/movie/188?api_key=b692b9da86f1cf0c1b623ea6e2770101
E/HttpHandler: IOException: https://api.themoviedb.org/3/movie/189?api_key=b692b9da86f1cf0c1b623ea6e2770101
E/HttpHandler: IOException: https://api.themoviedb.org/3/movie/190?api_key=b692b9da86f1cf0c1b623ea6e2770101
E/HttpHandler: IOException: https://api.themoviedb.org/3/movie/191?api_key=b692b9da86f1cf0c1b623ea6e2770101
E/HttpHandler: IOException: https://api.themoviedb.org/3/movie/192?api_key=b692b9da86f1cf0c1b623ea6e2770101

Some of the IOExceptions are just URL's that came back as null, as

{"status_code":34,"status_message":"The resource you requested could not be found."}

How can I slow down the for loop to not exceed the API call limit?

HttpHandler:

package com.example.zdroa.yplex;

import android.util.Log;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;

public class HttpHandler {
    private static final String TAG = HttpHandler.class.getSimpleName();

    public HttpHandler() {
    }

    public String makeServiceCall(String reqUrl) {
        String response = null;
        try {
            URL url = new URL(reqUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            // read the response
            InputStream in = new BufferedInputStream(conn.getInputStream());
            response = convertStreamToString(in);
        } catch (MalformedURLException e) {
            Log.e(TAG, "MalformedURLException: " + e.getMessage());
        } catch (ProtocolException e) {
            Log.e(TAG, "ProtocolException: " + e.getMessage());
        } catch (IOException e) {
            Log.e(TAG, "IOException: " + e.getMessage());
        } catch (Exception e) {
            Log.e(TAG, "Exception: " + e.getMessage());
        }
        return response;
    }
    private String convertStreamToString(InputStream is) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
        String line;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line).append('\n');
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }
}

My calls are made inside of an AsyncTask

class getWorkingIdsFromAPI extends AsyncTask<Void, Void, Void> {

    ArrayList<String> alPersonType;

    public getWorkingIdsFromAPI(ArrayList<String> arrayList) {
        alPersonType = new ArrayList<>(arrayList);
    }

    @Override
    protected Void doInBackground(Void... params) {

        final HttpHandler httpHandler = new HttpHandler();

        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
                           @Override
                           public void run() {
                               for (int i = 0; i < 200; i++) { //20000
                                   String JSONString = httpHandler.makeServiceCall("https://api.themoviedb.org/3/movie/" + i + "?api_key=" + API_KEY);

                                   if (JSONString != null) {
                                       try {
                                           JSONObject jsonObject = new JSONObject(JSONString);
                                           JSONArray jsonArray = jsonObject.getJSONArray("genres");

                                           boolean cont = true;

                                           for (int a = 0; a < jsonArray.length(); a++) {

                                               JSONObject jsonObject1 = jsonArray.getJSONObject(a);
                                               String string = jsonObject1.getString("name");

                                               for (int b = 0; b < alPersonType.size(); b++) {
                                                   if (string.equals(alPersonType.get(b))) {
                                                       cont = false;
                                                   }
                                               }
                                           }

                                           if (cont) {
                                               String id = String.valueOf(jsonObject.getInt("id"));
                                               System.out.println("ID:   " + id);

                                               switch (id.length()) {
                                                   case 1:
                                                       id = "0000" + id;
                                                       break;
                                                   case 2:
                                                       id = "000" + id;
                                                       break;
                                                   case 3:
                                                       id = "00" + id;
                                                       break;
                                                   case 4:
                                                       id = "0" + id;
                                                       break;
                                               }
                                               switch (i) {
                                                   case 1:
                                                       STRING_LIST_OF_IDS = STRING_LIST_OF_IDS + id;
                                                       break;
                                                   default:
                                                       STRING_LIST_OF_IDS = ", " + STRING_LIST_OF_IDS + id;
                                                       break;
                                               }
                                           }

                                       } catch (JSONException e) {
                                           e.printStackTrace();
                                       }
                                   }
                               }
                           }
                       }

                , 3000);


        return null;
    }


    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);

        //add STRING_LIST_OF_IDS
        getStringOfIdsFromDB();
    }
}

Upvotes: 1

Views: 1900

Answers (2)

Alok
Alok

Reputation: 881

You are doing it wrong as timer task will be repeated after each 3000 ms, it will execute all the request in the loop. you can change your code something like this.

 ArrayList<String> alPersonType;
  i=0; // initialise your variable once instead of each time in task

public getWorkingIdsFromAPI(ArrayList<String> arrayList) {
    alPersonType = new ArrayList<>(arrayList);
}
@Override
protected Void doInBackground(Void... params) {


    final HttpHandler httpHandler = new HttpHandler();

    Timer timer = new Timer();
    timer.schedule(new TimerTask() {
                       @Override
                       public void run() {
                           if(i < 200) { String JSONString = httpHandler.makeServiceCall("https://api.themoviedb.org/3/movie/" + i + "?api_key=" + API_KEY);

                               if (JSONString != null) {
                                   try {
                                       JSONObject jsonObject = new JSONObject(JSONString);
                                       JSONArray jsonArray = jsonObject.getJSONArray("genres");

                                       boolean cont = true;

                                       for (int a = 0; a < jsonArray.length(); a++) {

                                           JSONObject jsonObject1 = jsonArray.getJSONObject(a);
                                           String string = jsonObject1.getString("name");

                                           for (int b = 0; b < alPersonType.size(); b++) {
                                               if (string.equals(alPersonType.get(b))) {
                                                   cont = false;
                                               }
                                           }
                                       }

                                       if (cont) {
                                           String id = String.valueOf(jsonObject.getInt("id"));
                                           System.out.println("ID:   " + id);

                                           switch (id.length()) {
                                               case 1:
                                                   id = "0000" + id;
                                                   break;
                                               case 2:
                                                   id = "000" + id;
                                                   break;
                                               case 3:
                                                   id = "00" + id;
                                                   break;
                                               case 4:
                                                   id = "0" + id;
                                                   break;
                                           }
                                           switch (i) {
                                               case 1:
                                                   STRING_LIST_OF_IDS = STRING_LIST_OF_IDS + id;
                                                   break;
                                               default:
                                                   STRING_LIST_OF_IDS = ", " + STRING_LIST_OF_IDS + id;
                                                   break;
                                           }
                                       }

                                   } catch (JSONException e) {
                                       e.printStackTrace();
                                   }i++;//increase the counter 
                               }
                           }
                       }
                   }

            , 3000);return null;
}

Also you can have a different Approach with Thread.sleep() change your doin background like below

@Override
protected Void doInBackground(Void... params) {

    final HttpHandler httpHandler = new HttpHandler();

                           for (int i = 0; i < 200; i++) {try {
Thread.sleep(400);} catch (InterruptedException e) {
e.printStackTrace();} 
                              String JSONString = httpHandler.makeServiceCall("https://api.themoviedb.org/3/movie/" + i + "?api_key=" + API_KEY);

                               if (JSONString != null) {
                                   try {
                                       JSONObject jsonObject = new JSONObject(JSONString);
                                       JSONArray jsonArray = jsonObject.getJSONArray("genres");

                                       boolean cont = true;

                                       for (int a = 0; a < jsonArray.length(); a++) {

                                           JSONObject jsonObject1 = jsonArray.getJSONObject(a);
                                           String string = jsonObject1.getString("name");

                                           for (int b = 0; b < alPersonType.size(); b++) {
                                               if (string.equals(alPersonType.get(b))) {
                                                   cont = false;
                                               }
                                           }
                                       }

                                       if (cont) {
                                           String id = String.valueOf(jsonObject.getInt("id"));
                                           System.out.println("ID:   " + id);

                                           switch (id.length()) {
                                               case 1:
                                                   id = "0000" + id;
                                                   break;
                                               case 2:
                                                   id = "000" + id;
                                                   break;
                                               case 3:
                                                   id = "00" + id;
                                                   break;
                                               case 4:
                                                   id = "0" + id;
                                                   break;
                                           }
                                           switch (i) {
                                               case 1:
                                                   STRING_LIST_OF_IDS = STRING_LIST_OF_IDS + id;
                                                   break;
                                               default:
                                                   STRING_LIST_OF_IDS = ", " + STRING_LIST_OF_IDS + id;
                                                   break;
                                           }
                                       }

                                   } catch (JSONException e) {
                                       e.printStackTrace();
                                   }
                               }
                           }
                    ;


    return null;
}

Upvotes: 1

Sebastian Zdroana
Sebastian Zdroana

Reputation: 51

Put a Thread.sleep(duration); just after the loop start.

try {
    Thread.sleep(400);
} catch (InterruptedException e) {
    e.printStackTrace();
}

Takes a 400 ms. sleep every loop cycle.

Upvotes: 0

Related Questions