如何解决后台服务的 Volley Response 中的内存泄漏

How to solve Memory Leaks in Volley Response for a Background Service

我正在使用此服务通过 Volley 将位置发送到 Web 数据库。我已经和内存泄漏斗争了将近两个星期,但仍然无法解决。我浏览了所有相关问题,但找不到可行的解决方案。

当服务在后台 运行 时,它使用 Volley 发送位置,并且设备中的 Ram 使用率随着每个请求的发送而不断增加,直到它因 OutOfMemory 而崩溃或系统终止进程。我尝试删除缓存,尝试将服务设置为远程进程,以便在重新启动时清除进程内存,还有很多事情,但还无法解决,我很想在这里解决它。如果有人可以帮助我,我真的很感激。谢谢

所以,这是我的代码:

前台服务:

public int onStartCommand(final Intent intent, int flags, final int startId) {

    //Log.i(TAG,"onStartCommand");

    sessionManager = new SessionManager(ForeGroundService.this);

    sessionManager.checkLogin();
    if (sessionManager.isDayRunning().equals("1") && serviceStarted == 1)
        if (!mGoogleApiClient.isConnected()) mGoogleApiClient.connect();

    TimerForServiceDelay = new CountDownTimer( 5 * 60 * 1000, 60*1000) {

        @Override
        public void onTick(long l) {
            //Log.i(TAG,"onTick (onStartCommand)");
        }

        @Override
        public void onFinish() {

            //Log.i(TAG,"onFinish (onStartCommand)");

            String Location = "Location :: [" + Co_or[0] + "," + Co_or[1] + "]";

            Intent notificationIntent = new Intent(ForeGroundService.this, MainActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(ForeGroundService.this, 0, notificationIntent, 0);

            Notification notification = new NotificationCompat.Builder(ForeGroundService.this, LOCATION_SENDING_NOTIFICATION_CHANNEL_ID)
                    .setContentTitle("Service")
                    .setContentText(Location)  .setColor(getResources().getColor(R.color.colorPrimary))
                    .setSmallIcon(R.drawable.ic_my_location_black_24dp)
                    .setContentIntent(pendingIntent)
                    .setAutoCancel(true)
                    .build();

            SendCoordinatesToDatabase();

            if (sessionManager.isDayRunning().equals("0")) {
                mGoogleApiClient.disconnect();
                Log.i(TAG, "just before stop self");
                serviceStarted = 0;
                stopSelf();
            } else {
                //Log.i(TAG,"on else condition of stop self");
                ContextCompat.startForegroundService(getApplicationContext(), new Intent(ForeGroundService.this,ForeGroundService.class));
                startForeground(1, notification);
                //stopForeground(true);
            }
            stopSelf();
        }

    }.start();

    return Service.START_STICKY; //This allows to restart the service when get killed automatically (WORKING solution)

}    

发送坐标到数据库:

public void SendCoordinatesToDatabase() {

    final String URL_LOCATION = getResources().getString(R.string.URL_LOCATION);

    StringRequest stringRequest = new StringRequest(Request.Method.POST, URL_LOCATION, new Response.Listener<String>() {

        @Override
        public void onResponse(String response) {
            Log.i(TAG, "[" + response + "]");
            try {
                JSONObject jsonObject = new JSONObject(response);
                String success = jsonObject.getString("success");
                String message = jsonObject.getString("message");
                //Log.i(TAG, "[" + message + "]");
                if (success.equals("1")) {
                    // TODO: Do something later
                } else {
                    // TODO: Do something later
                }

            } catch (JSONException e) {
                e.printStackTrace();
                Log.i(TAG, "JSON Error : " + e.toString());
            }

        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {

        }
    }) {

        @Override
        public Request<?> setCacheEntry(Cache.Entry entry) {
            return super.setCacheEntry(null);
        }

        @Override
        public Cache.Entry getCacheEntry() {
            return null;
        }

        @Override
        public Request<?> setRequestQueue(RequestQueue requestQueue) {
            requestQueue.getCache().clear();
            return super.setRequestQueue(requestQueue);
        }

        @Override
        protected Map<String, String> getParams(){

            String[] all = collectParameters(row,samityAndBranchDistance);
            final String vendor = getVendor();

            Map<String, String> params = new HashMap<>();
            params.put("email", all[0]);
            params.put("lati", all[1]);
            params.put("longi", all[2]);
            params.put("near_sam_dis",all[3]);
            params.put("branch_dis",all[4]);
            params.put("loc_name",all[5]);
            params.put("vendor",vendor);
            return params;
        }

    };

    RequestQueue requestQueue;
    requestQueue = Volley.newRequestQueue(this);
    requestQueue.getCache().clear();
    requestQueue.add(stringRequest);

}

为什么要创建新的请求队列?请求队列应该是每个应用程序单例。如果你像这样创建一个新的每个请求,你将有可怕的性能和大量不需要的线程。这可能是你的问题。