0

I have an android app that most of its feature consumes an API. My client complained that the retrieving of data from the web api is very slow. I wonder what's causing this.

Here's a basic structure of how I do my calls:

String returnString = "";

    token = tokenBuilder.generateToken("Customers/All");

    try {
    HttpGet request = new HttpGet(apiUrl + "CustomerRewards/All?customerId=" + id);
    request.setHeader(HTTP.CONTENT_TYPE, "application/json");
    request.setHeader("AccountId", headerAccountId);
    request.setHeader("StoreId", headerStoreId);
    request.setHeader("AppKey", headerAppKey);
    request.setHeader("Token", token);

    HttpClient client = new DefaultHttpClient();

    HttpResponse response = client.execute(request);
    String responseString = EntityUtils.toString(response.getEntity());

    Log.i("Api Message", responseString);

    returnString = responseString;
    } catch (Exception e) {
        returnString = e.getMessage();
    }

    return returnString;

I'm calling this method from a progress dialog in order to display a loader while, retrieving data from the web API. Is there a better way to do this? Or is somewhat my android code affects its performance?

Here's the code on the calling progress dialog.

rewardsErrorMessage = "";

    progressBar = new ProgressDialog(this);
    progressBar.setCancelable(true);
    progressBar.setMessage("Loading info ...");
    progressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
    progressBar.setProgress(0);
    progressBar.setMax(100);
    progressBar.setCancelable(false);
    progressBar.show();

    apiLoadStatus = false;

    new Thread(new Runnable() {
        public void run() {
            while (!apiLoadStatus) {
                apiLoadStatus = RewardApi();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                        e.printStackTrace();
                      }

                    }
                if (apiLoadStatus) {
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                        progressBar.dismiss();
                    }
                  }}).start();

        progressBar.setOnDismissListener(new OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialog) {
                SetValues();
            }

        });

And here's the method that actually calls the api class that connects to the web api

ApiConnection api = new ApiConnection();

    try {
        Log.i("CustomerId", customerInfos.getString("customer_id", ""));
        transactionMessage = api.GetTransactions(customerInfos.getString("customer_id", ""));
        availableRewardsMessage = api.GetCustomerRewards(customerInfos.getString("customer_id", ""));

        try
        {
            if(transactionMessage.contains("Timestamp"))
            {
                Log.i("Transaction", "Success");
                GetPoints(transactionMessage);
            }
            if(!availableRewardsMessage.equals("[]") && !availableRewardsMessage.equals("[]"))
            {
                JSONObject rewardsJson = new JSONObject(availableRewardsMessage);
                availableRewardsMessage = rewardsJson.getString("AvailableRewards");
                hasRewards = true;
            }
            return true;
        }
        catch(Exception e)
        {
            rewardsErrorMessage = transactionMessage.replace('[', ' ').replace(']', ' ').replace('"', ' ');
        }



    } catch(Exception e) {
        e.printStackTrace();
        rewardsErrorMessage = e.getMessage();
        return true;
    }
    return true;

As you notice, I have two api calls here.

I really would like to speed up the retrieving of data. Or is the api I'm consuming that slow? Any ideas guys? Thanks!

Luke Villanueva
  • 2,030
  • 8
  • 44
  • 94
  • Can you combine the calls through a facade? That would presumably halve the time. – Elliott Frisch Apr 04 '14 at 21:50
  • I'd recommend using Google's Volley library. It's asynchronous and works quite well. You might also want to consider preloading/caching your data to make the app appear as responsive as possible. Finally, using a ProgressBar as you have is considered by some to be bad practice, especially if you don't allow it to be canceled. Why not load the info in the background so the rest of the app can be used during loading? – Justin Pollard Apr 04 '14 at 21:55
  • @ElliottFrisch - What do you mean by combining them? Can you elaborate it or set an axample? Thanks. – Luke Villanueva Apr 04 '14 at 22:36
  • @JustinPollard - I haven't tried google's volley library but I will look into it. I used the progress bar since the functionality of the apps depends on the data being retrieved. So if I make them cancelable and put it to background the app won't have any functionality at all. And the user might be surprised that something just popped up after the data was loaded on background – Luke Villanueva Apr 04 '14 at 22:38
  • I see, I see. Another option that is, in my opinion, a little less jarring to the user is displaying a ProgressBar rather than ProgressDialog. I'm just personally not a fan of something so obstructive as the ProgressDialog. Yea, I'd strongly suggest looking into Volley, which optimizes for various types of API calls and uses the correct http stack based on what's available. – Justin Pollard Apr 04 '14 at 22:42
  • @ljpv14 See [this](http://stackoverflow.com/questions/5242429/what-is-facade-design-pattern) question. – Elliott Frisch Apr 04 '14 at 23:04

1 Answers1

4

As you're probably aware, there are a number of factors that can affect HTTP service calls, of which the client code is only one:

  1. Network speed and latency
  2. Server availability and load
  3. Size of data payload
  4. Client device resources
  5. Client code

You really need to determine where the bottleneck(s) are in order to know where to try to optimize. Additionally, you should make sure that the server is using Gzip to compress the payload and add the following to your client code:

request.setHeader("Accept-Encoding", "gzip");
mikejonesguy
  • 9,779
  • 2
  • 35
  • 49