如何解决后台服务的 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);
}
为什么要创建新的请求队列?请求队列应该是每个应用程序单例。如果你像这样创建一个新的每个请求,你将有可怕的性能和大量不需要的线程。这可能是你的问题。
我正在使用此服务通过 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);
}
为什么要创建新的请求队列?请求队列应该是每个应用程序单例。如果你像这样创建一个新的每个请求,你将有可怕的性能和大量不需要的线程。这可能是你的问题。