Android和Java:减少服务循环中的内存使用量 [英] Android and Java: Reduce memory usage on a service loop

查看:84
本文介绍了Android和Java:减少服务循环中的内存使用量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Android服务使用这个线程每秒更新一个通知(注释并不真正相关):

 线程= new Thread(){
@Override
public void run(){
// Preparando lanotificaciónde Swap
NotificationCompat.Builder notificationSwap = $ b $ 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 seaMagic number

while(!stop){
String swapInfo = null;

try {// TODO:free devuelve siempre 4lí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
}
扫描仪扫描仪=新扫描仪(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 + =\\\
Libre:+ 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:¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿ Si pilla lainterrupciónno hace falta la variable stop
}
}
}
};

问题是它使用了大约20MB的内存,但是如果我取消注释//System.gc ();这个数字下降到约3 / 4MB,这是很多垃圾。但是每个循环运行整个垃圾收集器对我来说似乎都不是很有效,而且CPU使用率更高。



这就是为什么我不喜欢垃圾收集器,在c ++循环只是通过使用自动变量我不会有这个问题,但我认为这可能会更好地完成,因为我没有真正用于Java和Android都没有。



所以,我的主要问题是,如何以更有效的方式降低内存使用量?我还会提供更好的方法来提升Android上的通知,但我真正需要的是防止这种代码使用这么多内存。


$ b

更新:



答案是建议我关闭Stream,Scanner等,我不确定这是否需要或不需要(关闭流并且扫描仪不能解决问题),但我认为这不是问题,因为它们已被成功删除。



问题在于它们在被删除之前堆积如山我想在线程休眠之前删除它们,而不是等待垃圾收集器,因为据我所知,这不能在Java中完成,所以我需要更多的垃圾收集器友好方法。

解决方案


如何以更高效的方式降低内存使用量?

重要的是摆脱所有这个过程 - 分叉n onsense并将其替换为一个简单的调用到 getMemoryInfo() 。或者,使用JNI调用一些C API来获取内存信息。每秒钟拨一个程序在移动设备上非常浪费。此外,您无法知道每个设备上是否存在 free ,因为设备上的命令行二进制文件不是Android SDK的一部分,并且不能保证一致。

其次,使用 StringBuilder String.format()而不是字符串连接来构建您的通知文本。


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.

解决方案

how can I lower memory usage in a more eficient way?

The big thing would be to get rid of all of this process-forking nonsense and replace it with a simple call to getMemoryInfo(). Or, use JNI to call some C APIs to get your memory information. Forking a process every second is exceedingly wasteful on a mobile device. Besides, you have no way of knowing if free exists on every device, as on-device command-line binaries are not part of the Android SDK and are not guaranteed to be consistent.

Secondarily, use StringBuilder or String.format() rather than string concatenation to build up your Notification text.

这篇关于Android和Java:减少服务循环中的内存使用量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆