Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/232.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 简单活动导航的内存泄漏_Android_Memory Leaks_Xamarin_Xamarin.android - Fatal编程技术网

Android 简单活动导航的内存泄漏

Android 简单活动导航的内存泄漏,android,memory-leaks,xamarin,xamarin.android,Android,Memory Leaks,Xamarin,Xamarin.android,我目前正在开发一个Xamarin.Android应用程序,它包含许多活动,使用一个API返回图像,有时返回大量对象列表,因此我必须注意内存以避免OOM 但是,当我开始使用位图时,我终于有了一些。起初,我认为这是因为那些位图,所以我运行了一些测试。而事实似乎并非如此。我停用了API,所以我使用空的对象列表,没有图像。我仍然设法让我的应用程序内存使用率疯狂到最终崩溃 由于我无法在Visual Studio上安装Xamarin Profiler(不知道为什么,但不是这里主要关注的问题),我在我的设备上

我目前正在开发一个Xamarin.Android应用程序,它包含许多活动,使用一个API返回图像,有时返回大量对象列表,因此我必须注意内存以避免OOM

但是,当我开始使用位图时,我终于有了一些。起初,我认为这是因为那些位图,所以我运行了一些测试。而事实似乎并非如此。我停用了API,所以我使用空的对象列表,没有图像。我仍然设法让我的应用程序内存使用率疯狂到最终崩溃

由于我无法在Visual Studio上安装Xamarin Profiler(不知道为什么,但不是这里主要关注的问题),我在我的设备上安装了一个名为“英特尔性能查看器”的应用程序,该应用程序能够实时监控设备的RAM使用情况。我启动了我的应用程序,假设内存使用总量是2GB内存中的1.1GB。我单击了一个按钮,该按钮应该显示一个对象列表,但是当API关闭时,列表是空的。因此,该活动包含一个自定义appbar、两个按钮、一个空的listview和一个表示“list is empty”的文本。RAM消耗量从大约30MB增加到了这一活动。然后我按下返回按钮,调用Finish();在活动中,然后我回到主要位置。RAM消耗量从1到2MB下降

然后,如果我再继续那个活动,它就会开始,再吃掉30 MB,如果我继续在这样的活动之间切换,它最终会导致OOME

我试着在我的设备开发人员选项中检查“不要保留活动”,似乎它释放了更多的RAM(多么合乎逻辑),但仍然不是所有的。在内存耗尽之前,我必须进行更多的切换,但问题仍然存在

Finish不应该将活动中包含的所有数据都放在垃圾收集器中吗?我试着做GC.Collect();在我的OnDestroy中,没有效果

我不知道我是否误解了android上的内存工作原理,因为我对移动开发还比较陌生,但这让我很头疼。有什么帮助吗

谢谢

编辑:这是我得到的当它去OOM

    05-23 10:15:37.973 D/dalvikvm( 5049): GC_FOR_ALLOC freed 1587K, 3% free 248825K/256263K, paused 22ms, total 23ms
05-23 10:15:37.973 I/dalvikvm-heap( 5049): Grow heap (frag case) to 245.840MB for 2908172-byte allocation
05-23 10:15:38.029 D/dalvikvm( 5049): GC_CONCURRENT freed 127K, 2% free 2515
37K/256263K, paused 10ms+10ms, total 52ms
05-23 10:15:38.077 D/dalvikvm( 5049): GC_FOR_ALLOC freed 74K, 2% free 251463K/256263K, paused 23ms, total 23ms
05-23 10:15:38.077 I/dalvikvm-heap( 5049): Forcing collection of SoftReferences for 11632652-byte allocation
05-23 10:15:38.105 D/dalvikvm( 5049): GC_BEFORE_OOM freed 306K, 2% free 251156K/256263K, paused 29ms, total 29ms
05-23 10:15:38.105 E/dalvikvm-heap( 5049): Out of memory on a 11632652-byte allocation.
05-23 10:15:38.105 I/dalvikvm( 5049): "main" prio=5 tid=1 RUNNABLE
05-23 10:15:38.105 I/dalvikvm( 5049):   | group="main" sCount=0 dsCount=0 obj=0xa62704b0 self=0xb7c7b510
05-23 10:15:38.105 I/dalvikvm( 5049):   | sysTid=5049 nice=0 sched=0/0 cgrp=[fopen-error:2] handle=-1217084352
05-23 10:15:38.105 I/dalvikvm( 5049):   | schedstat=( 7886788399 5740305249 19539 ) utm=596 stm=192 core=0
05-23 10:15:38.117 E/mono-rt ( 5049): =================================================================
05-23 10:15:38.117 E/mono-rt ( 5049): Got a SIGSEGV while executing native code. This usually indicates
05-23 10:15:38.117 E/mono-rt ( 5049): a fatal error in the mono runtime or one of the native libraries 
05-23 10:15:38.117 E/mono-rt ( 5049): used by your application.
05-23 10:15:38.117 E/mono-rt ( 5049): =================================================================
05-23 10:15:38.117 E/mono-rt ( 5049): 
05-23 10:15:38.117 F/libc    ( 5049): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread 5049

我建议您阅读这篇关于以下内容的文章:

  • 1)
  • (二)
  • (三)

编辑:

试着这样做:

using Android.Content;
using Java.IO;
using System;

namespace SampleTest.Droid
{
    public class CacheManager
    {
        private static long MaxSize = 5242880L; // 5MB

        private CacheManager() { }

        public static void CacheData(Context context, Byte[] data, String name)
        {
            try
            {
                File cacheDir = context.CacheDir;
                long size = cacheDir.TotalSpace;
                long newSize = data.Length + size;

                if (newSize > MaxSize)
                {
                    CleanDir(cacheDir, newSize - MaxSize);
                }

                File file = new File(cacheDir, name);
                FileOutputStream OS = new FileOutputStream(file);

                try
                {
                    OS.Write(data);
                }
                catch (Exception ex)
                {
                    OS.Flush();
                    OS.Close();
                    System.Console.WriteLine(ex.Message);
                    throw;
                }
            }
            catch (IOException ex)
            {
                System.Console.WriteLine(ex.Message);
                throw;
            }
        }

        private static void CleanDir(File dir, long bytes)
        {
            long bytesDeleted = 0;
            File[] files = dir.ListFiles();

            foreach (File file in files)
            {
                bytesDeleted += file.Length();
                file.Delete();

                if (bytesDeleted >= bytes)
                    break;
            }
        }

        public static byte[] RetrieveData(Context context, String name)
        {
            try
            {

                File cacheDir = context.CacheDir;
                File file = new File(cacheDir, name);

                if (!file.Exists())
                {
                    // Data doesn't exist
                    return null;
                }

                byte[] data = new byte[(int)file.Length()];
                FileInputStream fis = new FileInputStream(file);
                try
                {
                    fis.Read(data);
                }
                finally
                {
                    fis.Close();
                }
                return data;
            }

            catch (Exception ex)
            {
                System.Console.WriteLine(ex.Message);
                throw;
            }
        }

        private static long DirSize(File Dir)
        {
            long size = 0;
            File[] files = Dir.ListFiles();

            foreach (File file in files)
            {
                if (file.IsFile)
                    size += file.Length();
            }
            return size;
        }
    }
}

参考:

我建议您阅读这篇关于以下内容的文章:

  • 1)
  • (二)
  • (三)

编辑:

试着这样做:

using Android.Content;
using Java.IO;
using System;

namespace SampleTest.Droid
{
    public class CacheManager
    {
        private static long MaxSize = 5242880L; // 5MB

        private CacheManager() { }

        public static void CacheData(Context context, Byte[] data, String name)
        {
            try
            {
                File cacheDir = context.CacheDir;
                long size = cacheDir.TotalSpace;
                long newSize = data.Length + size;

                if (newSize > MaxSize)
                {
                    CleanDir(cacheDir, newSize - MaxSize);
                }

                File file = new File(cacheDir, name);
                FileOutputStream OS = new FileOutputStream(file);

                try
                {
                    OS.Write(data);
                }
                catch (Exception ex)
                {
                    OS.Flush();
                    OS.Close();
                    System.Console.WriteLine(ex.Message);
                    throw;
                }
            }
            catch (IOException ex)
            {
                System.Console.WriteLine(ex.Message);
                throw;
            }
        }

        private static void CleanDir(File dir, long bytes)
        {
            long bytesDeleted = 0;
            File[] files = dir.ListFiles();

            foreach (File file in files)
            {
                bytesDeleted += file.Length();
                file.Delete();

                if (bytesDeleted >= bytes)
                    break;
            }
        }

        public static byte[] RetrieveData(Context context, String name)
        {
            try
            {

                File cacheDir = context.CacheDir;
                File file = new File(cacheDir, name);

                if (!file.Exists())
                {
                    // Data doesn't exist
                    return null;
                }

                byte[] data = new byte[(int)file.Length()];
                FileInputStream fis = new FileInputStream(file);
                try
                {
                    fis.Read(data);
                }
                finally
                {
                    fis.Close();
                }
                return data;
            }

            catch (Exception ex)
            {
                System.Console.WriteLine(ex.Message);
                throw;
            }
        }

        private static long DirSize(File Dir)
        {
            long size = 0;
            File[] files = Dir.ListFiles();

            foreach (File file in files)
            {
                if (file.IsFile)
                    size += file.Length();
            }
            return size;
        }
    }
}

请参阅:

用片段替换活动。活动很繁重,我想你会继续在导航上添加新的活动。 在你知道事情会很容易失控,你的应用程序会达到OOM阈值之前。保持单个活动并替换其中的片段


这是一个关于fragment

用fragment替换活动的教程。活动很繁重,我想你会继续在导航上添加新的活动。 在你知道事情会很容易失控,你的应用程序会达到OOM阈值之前。保持单个活动并替换其中的片段


这是一个关于片段的教程,好的,好消息(有点)。问题不在我最初认为的地方。我把这个内存问题放在一边几个小时,继续开发应用程序的最后几个功能。在测试我的新代码时,在获得OOM之前,我无法在活动之间导航超过三次。我就像是“等一下,我可以切换几个小时而不会出错”。因此,我使用Git找到了这个内存泄漏问题的第一个提交。它最早是以照片上传功能出现的。所以,我的内存泄漏可能是因为一些不可回收的位图。有很多位图内存错误,可以在堆栈和互联网上的其他地方找到,我应该能够找到它。感谢所有回复的人

好的,好消息(有点)。问题不在我最初认为的地方。我把这个内存问题放在一边几个小时,继续开发应用程序的最后几个功能。在测试我的新代码时,在获得OOM之前,我无法在活动之间导航超过三次。我就像是“等一下,我可以切换几个小时而不会出错”。因此,我使用Git找到了这个内存泄漏问题的第一个提交。它最早是以照片上传功能出现的。所以,我的内存泄漏可能是因为一些不可回收的位图。有很多位图内存错误,可以在堆栈和互联网上的其他地方找到,我应该能够找到它。感谢所有回复的人

我已经读过其中一些,我从中了解到(也许我错了),当一个活动完成时,它仍然保存在内存中,以便更快地重新启动它,但当可用内存不足时,它将被释放。但这似乎永远不会发生,内存会一直增加,直到达到最大堆大小。当我得到OOM时,我会添加一些堆栈跟踪。我已经阅读了其中的一些,我从中了解到(可能我错了),当一个活动完成时,它仍然保留在内存中,以便更快地重新启动,但在可用内存不足时会被释放。但这似乎永远不会发生,内存会一直增加,直到达到最大堆大小。我将添加一点当我得到OOM时的堆栈跟踪。我开始使用片段有点晚,并且已经有大量的活动完成了。我将在下一个应用程序中只使用一个活动和片段,但对于这一个,工作离结束太近,最后期限是两天,所以我现在无法真正修改所有内容。。这就是为什么我在寻找一种方法来清除这种奇怪的内存消耗。。但使用片段是一个非常好的解决方案,我开始使用片段有点晚了,而且已经有大量的活动完成了。我将只使用一个活动和o