Rob85
Rob85

Reputation: 1729

Memory Leak with AsyncTask

i appear to have a memory leak with the following asyncTask, what possible cause are there?

/**
 * Async task class to get json by making HTTP call
 * */
public class PostLocation extends AsyncTask<String, Void, String>
{

    @Override
    protected void onPreExecute()
    {

    }
    @Override
    protected String doInBackground(String... params)
    {
        try
        {
            String response = "";



            URL url = new URL(BASE_URL + "receiveLocation.php");

            myConnection = (HttpURLConnection) url.openConnection();
            myConnection.setRequestMethod("POST");
            myConnection.setDoOutput(true);

            DataOutputStream wr = new DataOutputStream(myConnection.getOutputStream());

            wr.writeBytes(params[0]);
            int responseCode = myConnection.getResponseCode();

            if (responseCode == HttpsURLConnection.HTTP_OK)
            {
                String line;
                BufferedReader br = new BufferedReader(new InputStreamReader(myConnection.getInputStream()));
                while ((line = br.readLine()) != null)
                {
                    response += line;
                }
            }
            else
            {
                return response = "";
            }
            return response;


        }
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return "false";
        }
    }
    @Override
    protected void onPostExecute(String result)
    {
        if(result.equals("success"))
        {
            myConnection.disconnect();
        }


    }

}

this is simply posting some data to my server. What could be causing memory leaks, note this task is called in the background from a broadcast receiver using goAsync

Upvotes: 2

Views: 2248

Answers (2)

Kelevandos
Kelevandos

Reputation: 7082

The problem here is in your class structure.

A nested class should be declared static whenever possible, otherwise it will keep the enclosing class in memory, leading to memory leaks.

Change:

public class PostLocation extends AsyncTask<String, Void, String>

to:

public static class PostLocation extends AsyncTask<String, Void, String>

Here is an exercise:

  • Put a field called boolean test in your BroadcastReceiver class
  • Now in your nested class, try to access this field, e.g. test == true

If the nested class is not static, you will be able to access the field. This is because the instance of the class keeps the reference to the enclosing class. But if you make PostLocation class static, the field will not be available.

Upvotes: 3

Sohail Zahid
Sohail Zahid

Reputation: 8149

Yes you need to close the inputstream first and close httpconnection next. As per javadoc.

Each HttpURLConnection instance is used to make a single request but the underlying network connection to the HTTP server may be transparently shared by other instances. Calling the close() methods on the InputStream or OutputStream of an HttpURLConnection after a request may free network resources associated with this instance but has no effect on any shared persistent connection. Calling the disconnect() method may close the underlying socket if a persistent connection is otherwise idle at that time.

Source

Upvotes: 1

Related Questions