2016-10-10 24 views
2

私は、1つのAndroidアプリのメモリが16MBに制限されていると読んだことがあります(一部のデバイスの方が高くなる可能性があります)。だから、それはネットワークからのいくつかのデータ(画像など)の読み込みには真実です。Androidのメモリ制限テストの問題?

私の仮想デバイス(Android用のVisual Studioエミュレータ)では、メモリの制限は約46MBです。私はOutOfMemoryExceptionを投げる前に読み込むことができるイメージの数が46イメージ(各イメージは約1MBのサイズを持つため)だと思います。

最初は、画像がImageViews(ListViewまたはRecyclerViewの項目にラップされている)に表示されている場合のみ、メモリが超過する可能性があると考えました。しかし、ロードされた画像が表示されているかどうかに関わらず、例外はスローされます(出力ウィンドウで見ることができます)。

私は、List<int>のような項目の数が約13 000 000(46MBを超えるはずです)のようなローカルリストをロードするなど、OutOfMemoryExceptionを再現したいと考えています。ただし、例外はスローされません。私は130 000 000にアイテムの数を増やしてみましたが、まだ同じ例外が投げられません。ここにコードです:

//the local list is declared inside my main Activity class 
List<int> _ints = new List<int>(); 
for(var i = 0; i < 130000000; i++) { 
    _ints.Add(i); 
} 

私は間違った方法でOutOfMemoryExceptionの原因を理解しているようです。あなたはこれを私に説明するか、可能であればOutOfMemoryExceptionを再現するためのコード例や提案を与えてもらえますが、ネットワークから何かをダウンロードすることには関係しません。できるだけシンプルに保つことを意味します。

ありがとうございました!

答えて

1

OutOfMemoryExceptionあなたはJava側から来ています。 C#オブジェクトのみを使用して再現することはできません。

大きなJavaオブジェクトを割り当てる必要があります。 C#コードから参照できるJavaオブジェクトの数には限界があるため、多くの小さなオブジェクトでは機能しません。

Android.Graphics.Bitmapは良い候補です:

List<Bitmap> _ints = new List<Bitmap>(); 
for (var i = 0; i < 130000000; i++) 
{ 
    _ints.Add(Bitmap.CreateBitmap(1000, 1000, Bitmap.Config.Argb8888)); 
} 

(モノ例外にラップされた)結果のJava例外:

Java.Lang.OutOfMemoryError: Failed to allocate a 4000012 byte allocation with 219956 free bytes and 214KB until OOM 
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() [0x0000c] in <368820a9888f43ddb85d18e87189adbf>:0 
    at Java.Interop.JniEnvironment+StaticMethods.CallStaticObjectMethod (Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfomethod, Java.Interop.JniArgumentValue* args) [0x00082] in <a043032cf94a485190047a14918b9f60>:0 
    at Java.Interop.JniPeerMembers+JniStaticMethods.InvokeObjectMethod (System.String encodedMember, Java.Interop.JniArgumentValue* parameters) [0x00019] in <a043032cf94a485190047a14918b9f60>:0 
    at Android.Graphics.Bitmap.CreateBitmap (System.Int32 width, System.Int32 height, Android.Graphics.Bitmap+Config config) [0x0005e] in <3140893b79904cefbb68181cd89998e0>:0 
    at SomeActivity.OnCreate (Android.OS.Bundle savedInstanceState) [0x00024] in <efd0cb86bcd8422d9a46a0a8a1804b4d>:0 
    at Android.Support.V4.App.FragmentActivity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00011] in <71c3e52f1b484794bca1cdfb1b8b1fdb>:0 
    at (wrapper dynamic-method) System.Object:46337ec2-c41a-4805-8728-4ab907d01a03 (intptr,intptr,intptr) 
    --- End of managed Java.Lang.OutOfMemoryError stack trace --- 
    java.lang.OutOfMemoryError: Failed to allocate a 4000012 byte allocation with 219956 free bytes and 214KB until OOM 
     at dalvik.system.VMRuntime.newNonMovableArray(Native Method) 
     at android.graphics.Bitmap.nativeCreate(Native Method) 
     at android.graphics.Bitmap.createBitmap(Bitmap.java:812) 
     at android.graphics.Bitmap.createBitmap(Bitmap.java:789) 
     at android.graphics.Bitmap.createBitmap(Bitmap.java:756) 
     at md53b9888b0c3fe89a24cb980ab2ea2a8a2.SomeActivity.n_onCreate(Native Method) 
     at md53b9888b0c3fe89a24cb980ab2ea2a8a2.someActivity.onCreate(SomeActivity.java:32) 
     at android.app.Activity.performCreate(Activity.java:5990) 
     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106) 

は編集:2があるので、Xamarinでメモリの問題はより複雑ですガベージコレクタ、およびビットマップのようなオブジェクトの両方に存在します。

これはHelping the GC

+0

あなたの説明は私にとって理にかなっていますが、これはここで最善の答えと思われますので、すぐにそれを受け入れます。ありがとうございました :)。ところで、私の実際の問題は、多くの画像を読み込むことです。しかし、私はそれらをすべて表示する必要はありません。現在のところ、問題は十分な画像を表示した後(リストをスクロールすることによって)、次の画像(継続的なスコリングによる)は表示されません(メモリがいっぱいであるとは思わない)。イメージローダーライブラリを使用しようとしたことはありません。問題をよりよく理解するために、これを最初に解決したいからです。もしあなたがこの解決策に関する提案があれば、本当に感謝します:) – Hopeless

+0

xamarinのドキュメントへのリンクが追加されました。ところで、例外はどこで起こりますか?ビットマップ割り当てになっていますか? – bwt

+0

私は実際にはわかりませんが、画像が表示されないスクロールの位置では、出力で「OutOfMemoryException'のようなメッセージを見ることができます。しかし、ヒープメモリをデバッグしようとすると、画像が大きく異なった点で表示されてしまうのは奇妙です(1点は約123MB、もう1点は約85MBです)。実際には画像はロードされません(私はasync/awaitを使用しています)。だから私は問題がメモリの制限ではないかもしれないと思うようになります。 – Hopeless

1
public void OOMTest() throws Exception { 
    int count = 20; 
    System.out.println("\n=================> started..\n"); 
    for (int itrator = 1; itrator < 100; itrator++) { 
     System.out.println("Iteration " + itrator + " Free Mem: " 
       + Runtime.getRuntime().freeMemory()); 
     int[] memoryFillIntVar = new int[count]; 
     count = count * 5; 
     System.out.println("\nRequired Memory for next loop: " + count); 
     Thread.sleep(1000); 
    } 
} 
+0

GlidePicassoは、しかし、より多くの説明は良いはず追加、あなたの答えをいただき、ありがとうございます。とにかく私はあなたに1つの投票を与えたいと思います。これはまだ役に立ちます。 – Hopeless

1

ヒープサイズに関しては、アプリケーションによって異なりますが、電話によって異なります。これは製造元から設定され、最小値は通常16MBです。 Androidマニフェストで大きなヒープをマークすることでアプリ内の大きなヒープを使用することができますが、これは最後の手段として使用して、空きメモリを獲得するためにバックグラウンドにある他のアプリを強制終了させます。

あなたのケースでは、画像が表示されなくても、他のオブジェクトが参照を保持している場合、アプリのメモリにまだ残っている可能性があることに注意してください。 Androidでのイメージの読み込みと管理は、通常、ヒープのメモリの制約のために問題があります。この問題を克服するため、Facebookは独自の画像ローディングライブラリFrescoを作成しました。このライブラリでは、別のヒープを使用してメモリを読み込み、アプリ内の他のオブジェクトで使用されていたスペースを使用しません。たくさんの画像を扱う場合は、アプリに紹介することを検討してください。

+0

フレスコ画の使用についてのご意見ありがとうございます。イメージローダーライブラリを使用してみましたが、これは私の最後の手段です。また、私はXamarinでプログラミングしているので、XamarinにFrescoのラッパーがあるかどうかはわかりません。私はXamarinで利用可能なGlideのような別のイメージローダーライブラリを知っています。 – Hopeless

1

画像をメモリに取るサイズが1メガバイトではない特別な章、Xamarin documentationに説明され、画像がメモリに取ることが実際のサイズは、以下のようにカウントすることができますあなたは画像2000x1250があると仮定します。それは4x2000x1250バイトのメモリが必要です。 各ピクセルには、赤、緑、青、アルファチャンネル情報の一部があります。

だから、メモリにかかる実際のサイズは、画像を読み込むための最良の方法4x2000x1250=10000000 Byte -> 9.5MB

ようなものになるだろうライブラリを使用している、図書館は、など、それらをキャッシュする、ビットマップをリサイクルして画像を読み込むの世話をよくします

私の好きなものを集めたものです。あなたのニーズに合ったものを試してみることができます。私はいつも最初のものを好む。 Fresco

+0

はい、メモリに読み込まれた画像のサイズは正しいです。とにかくあなたの答えに感謝します。イメージローダーライブラリに関するあなたの提案も役立ちます。 – Hopeless