【问题标题】:Memory Leak with AsyncTaskAsyncTask 的内存泄漏
【发布时间】:2017-05-16 15:00:30
【问题描述】:

我似乎有以下 asyncTask 的内存泄漏,可能是什么原因?

/**
 * 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();
        }


    }

}

这只是将一些数据发布到我的服务器。什么可能导致内存泄漏,注意这个任务是在后台使用 goAsync 从广播接收器调用的

【问题讨论】:

  • 添加 logcat 将提供有关问题的更多信息,请添加它。
  • 这个类是放在单独的.java文件中还是嵌套类?
  • @Kelevandos 它是我的广播接收器内部的一个内部类
  • 请看答案

标签: android memory-leaks android-asynctask


【解决方案1】:

这里的问题在于你的类结构。

嵌套类应该尽可能声明为static,否则它会将封闭类保留在内存中,导致内存泄漏。

变化:

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

到:

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

这是一个练习:

  • 在 BroadcastReceiver 类中添加一个名为 boolean test 的字段
  • 现在在您的嵌套类中,尝试访问该字段,例如test == true

如果嵌套类不是静态的,您将能够访问该字段。这是因为类的实例保留了对封闭类的引用。但如果你将PostLocation 类设为static,则该字段将不可用。

【讨论】:

  • 我在这里做两个答案,但是每次调用这个任务都会增加大约 0.1 mb 的 ram 使用量,这个调用每 3 分钟运行一次,如果我删除调用它不会增加
【解决方案2】:

是的,您需要先关闭输入流,然后再关闭 httpconnection。根据javadoc

每个 HttpURLConnection 实例用于发出单个请求,但 与 HTTP 服务器的底层网络连接可能是 由其他实例透明共享。调用 close() 方法 在 HttpURLConnection 的 InputStream 或 OutputStream 之后 请求可能会释放与此实例关联的网络资源,但 对任何共享持久连接没有影响。调用 disconnect() 方法可能会关闭底层套接字,如果持久 那时连接处于空闲状态。

Source

【讨论】:

  • 考虑到其他答案,如果类是静态的,我不能像上面那样关闭连接,还是我只是将连接和输入流设为静态?
  • doInBackgroundreturn response;之前尝试在br.close();之前关闭
  • 我在这里做了两个答案,但是每次调用这个任务都会增加大约 0.1 mb 的内存使用,这个调用每 3 分钟运行一次,如果我删除调用它不会增加
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-13
  • 2021-12-27
  • 1970-01-01
  • 2011-03-03
  • 2017-01-31
  • 2015-04-04
  • 1970-01-01
相关资源
最近更新 更多