I have an Android Service which updates a notification every second using this Thread (comments are not really relevant):
thread = new Thread() {
@Override
public void run() {
// Preparando la notificación de Swap
NotificationCompat.Builder notificationSwap =
new NotificationCompat.Builder(context)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle("Notificator:");
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
int notificationSwapId = 1; // TODO: Asignar un ID que no sea "Magic number"
while (!stop) {
String swapInfo = null;
try{ // TODO: free devuelve siempre 4 líneas?
Process free = Runtime.getRuntime().exec("free");
BufferedReader freeOut =
new BufferedReader(
new InputStreamReader(new DataInputStream(free.getInputStream())));
free.waitFor();
freeOut.readLine();
freeOut.readLine();
freeOut.readLine();
swapInfo = freeOut.readLine();
}catch(Exception e){
Log.e("ERROR", e.toString()); // TODO: Mejorar esto
}
Scanner scanner = new Scanner(swapInfo); // TODO: Mejorar esto
String swapInfo2 = null;
if (scanner.hasNext()) {
scanner.skip("Swap:");
}
if (scanner.hasNextInt()) {
/*swapInfo2 = "Total: " + */scanner.nextInt();
}
if (scanner.hasNextInt()) {
swapInfo2 = "Usado: " + scanner.nextInt();
}
if (scanner.hasNextInt()) {
swapInfo2 += "\nLibre: " + scanner.nextInt();
}
// Notificando
notificationSwap.setContentText(swapInfo2);
notificationManager.notify(notificationSwapId, notificationSwap.build());
// Intentando liberar memoria
//System.gc();
try {
Thread.sleep(new Integer(PreferenceManager.getDefaultSharedPreferences(context).getString("frecuency", "60000"))); // TODO: Mejorar esto
} catch (InterruptedException e){
Log.d("Notificator (Service)", "Deteniendo el hilo durante la espera"); // TODO: Mejorar esto
// TODO: ¿Qué pasa si el hilo es interrumpido fuera del try/catch? Si pilla la interrupción no hace falta la variable stop
}
}
}
};
The problem is that it uses about 20MB of memory but if I uncomment the "//System.gc();" line that number lowers to about 3/4MB, thats A LOT of garbage. But running the whole Garbage Collector every loop does not seem very efficient to me, and CPU usage goes higher.
Thats why I don't like garbage collectors, on a c++ loop just by using auto variables I wouldn't have this problem, but I think this could be better done since I'm not really used neither to Java nor Android.
So, my main question is, how can I lower memory usage in a more eficient way? I also would apreciate better ways to uptate a notification on Android but what I really need is to prevent this kind of code from using so many memory.
UPDATE:
Answers are suggesting that I should close the Stream, the Scanner, etc, I'm not really sure whether this is necesary or not (closing the stream and the scanner does not solve the problem) but I think that's not the problem since they are being succesfully deleted anyway.
The problem is that they pile up before being deleted and I want to delete them just before the thread sleeps instead of waiting to the garbage collector, and since that cannot be done in Java as far as I know, I need a more "garbage collector friendly" aproach.