Android和Java:减少服务循环中的内存使用量

时间:2016-07-01 10:57:30

标签: java android garbage-collection

我有一个Android服务,它使用此线程每秒更新一次通知(评论并不真正相关):

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
            }
        }
    }
};

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

这就是为什么我不喜欢垃圾收集器,只是通过使用自动变量在c ++循环中我不会遇到这个问题,但我认为这可能会更好,因为我并不是真的既不用于Java也不用于Android。

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

更新

答案表明我应关闭Stream,Scanner等,我不确定这是否是必要的(关闭流并且扫描仪无法解决问题)但我认为&# 39;不是问题,因为无论如何它们都被成功删除了。

问题是它们在被删除之前堆积起来我想在线程休眠之前删除它们而不是等待垃圾收集器,因为据我所知,这不能用Java完成,我需要更多"垃圾收集器友好"的形式给出。

2 个答案:

答案 0 :(得分:0)

在finally块中你可以做以下事情

 finally {
try {
    freeOut.close();
} catch (IOException e) {
    e.printStackTrace();
}

答案 1 :(得分:0)

  

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

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

其次,使用StringBuilderString.format()而不是字符串连接来构建您的Notification文字。