Laden Sie große Bilder in Android und die Vermeidung von out-of-memory-Fehler?
Arbeite ich an einer app, die verwendet große Bilder (1390 × 870 : 150 Kb - 50 Kb). Ich bin das hinzufügen von Bildern, wie ich Tippen Sie auf einen trigger/Bildansicht.
An einem bestimmten Punkt bin ich immer ein out of memory " - Fehlermeldung:
java.lang.OutOfMemoryError
E/AndroidRuntime(23369): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
E/AndroidRuntime(23369): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:613)
E/AndroidRuntime(23369): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:378)
Um die Größe des Bildes, ich bin dabei:
Bitmap productIndex = null;
final String imageLoc = IMAGE_LOCATION;
InputStream imageStream;
try {
imageStream = new FileInputStream(imageLoc);
productIndex = decodeSampledBitmapFromResource(getResources(), imageLoc, 400, 400);
productIV.setImageBitmap(productIndex);
} catch (FileNotFoundException e1) {
//TODO Auto-generated catch block
e1.printStackTrace();
}
}
public static Bitmap decodeSampledBitmapFromResource(Resources res, String resId, int reqWidth, int reqHeight) {
//First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(resId, options);
//Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
//Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(resId, options);
}
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
//Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 3;
final int halfWidth = width / 3;
//Calculate the largest inSampleSize value that is a power of 2 and keeps both
//height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
Habe ich diese Art der Größenänderung, um Speicherplatz zu sparen aus dem Android-Docs:
Laden Von Großen Bitmaps Effizient
Den log nach dieser wie ist der Täter in der decodeSampledBitmapFromResource
Methode :
return BitmapFactory.decodeFile(resId, options);
- - - - - - edit - - - - - -
Hier ist, wie ich hinzufüge, jedes Element, auf das FrameLayout.
for(int ps=0;ps<productSplit.size();ps++){
//split each product by the equals sign
List<String> productItem = Arrays.asList(productSplit.get(ps).split("="));
String tempCarID = productItem.get(0);
tempCarID = tempCarID.replace(" ", "");
if(String.valueOf(carID).equals(tempCarID)){
ImageView productIV = new ImageView(Configurator.this);
LayoutParams productParams = new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
productIV.setId(Integer.parseInt(partIdsList.get(x)));
productIV.setLayoutParams(productParams);
final String imageLoc = productItem.get(2);
InputStream imageStream;
try {
imageStream = new FileInputStream(imageLoc);
productIndex = decodeSampledBitmapFromResource(getResources(), imageLoc, 400, 400);
productIV.setImageBitmap(productIndex);
} catch (FileNotFoundException e1) {
//TODO Auto-generated catch block
e1.printStackTrace();
}
productLayers.addView(productIV);
}
}
InformationsquelleAutor der Frage dcp3450 | 2014-01-27
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie eine andere bitmap-config zu stark verringern Sie die Größe der Bilder. Der Standardwert ist " RGB-config ARGB8888 also vier 8-bit-Kanäle (rot, grün, blau, alhpa). Alpha ist die Transparenz der bitmap. Diese nehmen eine Menge von Speicher - imagesize X 4. Also, wenn die imagesize ist 4 megapixel, 16 MB wird sofort dem heap zugeordnet werden - schnell anstrengend Speicher.
Statt - verwenden RGB_565 die zum Teil verschlechtert die Qualität - aber zum Ausgleich können Sie Dithering der Bilder.
Sich also Ihre Methode decodeSampledBitmapFromResource - fügen Sie den folgenden Schnipsel:
In Ihrem code:
Referenzen:
http://developer.android.com/reference/android/graphics/Bitmap.Config.html#ARGB_8888
InformationsquelleAutor der Antwort Björn Hallström
Hochauflösenden Geräten wie dem S4 laufen in der Regel out of memory, wenn Sie nicht haben, Ihr image in den richtigen Ordner, die
drawable-xxhdpi
. Sie können auch Ihr Bild indrawable-nodpi
. Der Grund, es würde ausgehen, memorey, wenn Ihr Bild nur indrawable
dass die android würde das Bild zu skalieren, zu denken, dass das Bild wurde speziell für niedrige Auflösung.InformationsquelleAutor der Antwort serge
Können Sie dieses schöne Bibliothek https://github.com/davemorrissey/subsampling-scale-image-view
InformationsquelleAutor der Antwort Rohit Arya
Here is how I'm adding each item to the FrameLayout
das ist das problem, den code halten Sie das hinzufügen, und hinzufügen von mehr Bilder, und egal, wie gut Sie die Größe oder wie viel Speicher das Gerät haben, an einem bestimmten Punkt WIRD es run out of memory. Das ist, weil jedes Bild, das Sie hinzufügen, es bleibt in Erinnerung.
Für diese Art von situation, was die apps tun, ist die Verwendung einer ViewGroup, kann recycelt Ansichten. Ich weiß nicht, Ihr layout, aber in der Regel ist ein
ListView
GridView
oder eineViewPager
durch das recycling von Ansichten, die Sie re-verwenden Sie den layout-und können über die re-das laden von Bildern als notwendig.Für den spezifischen Zweck des be-und Größenanpassung der Bilder empfehle ich dringend die Verwendung Picasso Bibliothek, wie es ist SEHR gut geschrieben, einfach zu bedienen und stabil.
InformationsquelleAutor der Antwort Budius
Sind Sie immer noch zu verwalten müssen die bitmap-Speicher als würde ich nicht versuchen zu reservieren, die Gesamtfläche mehr als 3x die Größe des Bildschirms (wenn Sie darüber nachdenken, macht es Sinn, für scrolling-Verhalten). Wenn Sie die überlagerung eines Bildes auf ein anderes, an einem gewissen Punkt, Sie schlagen eine " Out Of Memory Fehler. Können Sie müssen sich auf die Erfassung der Vorherige Bild als einzelnes Bild im hintergrund, um sicherzustellen, dass Sie immer noch passen in den verfügbaren Speicher. Oder wenn ein neues Bild überlappt einen bestehenden Bild nur laden und Rendern der sichtbare Teil. Wenn performance ein Problem wird, dann müssen Sie prüfen, OpenGL Texturen, aber die memory-allocation-problem ist immer noch das gleiche.
Tun, gehen durch alle die Anzeige Von Bitmaps Ausbildung als es sollte Ihnen einige weitere Ideen, wie Sie zu handhaben display.
InformationsquelleAutor der Antwort Morrison Chang
Verwenden Fresco-Bibliothek zum laden von großen Bildern wird diesen Fehler vermeiden.
in xml-layout
und im javacode
InformationsquelleAutor der Antwort lee