проекта с ошибкой на GitHub: https://github.com/MediaPortal1/HowToDraw/blob/master/app/src/main/java/com/poltavets/app/setImageBitmap Ошибка, ImageView вызов OutOfMemory
Я имел метод img.setImageResources (R.id.image) в моем проекте, но это offten называют OutOfMemory, когда я использую этот метод часто или изменения ориентация экрана. Я нашел эту статью о загрузке растровых изображений «правильных»: https://developer.android.com/training/displaying-bitmaps/load-bitmap.html копипаст 2 последних методы этой статьи, и изменить свой код от:
imageView.setImageResource(image);
К:
Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
if(getRequestedOrientation()==ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
imageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(), msg.what,100,100));
else imageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(), msg.what,400,400));
}
};
handler.sendEmptyMessage(image);
Я поставил этот методы Handler и работа была быстрее. И я добавляю условия ориентации, потому что в land-orietation ImageView меньше, а растровое изображение должно иметь меньшее разрешение. Он работал нормально, everithink было нормально. Но я работал с другими деталями в этом проекте (просто добавьте изображения в свой проект) и дважды заново создайте этот проект, а ошибка OutOfMemory появляется снова, когда я начинаю свою деятельность. Прежде чем эта ошибка возникла не всегда, но теперь она возникла ВСЕГДА, когда я запускаю Activity! Как? Я не собираю код этой деятельности? Мои изображения очень низкомоторные. Максимальный размер изображений 200кб. Как изображение размером 100 КБ может вызывать OutOfMemory?
Ошибка:
Process: com.poltavets.app.howtodraw, PID: 28720 java.lang.OutOfMemoryError: Failed to allocate a 35389452 byte allocation with 5482128 free bytes and 5MB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:655)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:488)
at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:511)
at com.poltavets.app.howtodraw.view.HowTo.decodeSampledBitmapFromResource(HowTo.java:224)
at com.poltavets.app.howtodraw.view.HowTo$3.handleMessage(HowTo.java:185)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5546)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:964)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:759)
Код ChangeImage (Ошибка здесь):
public void changeImageSrc(int image,int count,int position,String name) {
filename=name+"_"+image+"_"+position;
imagenumber=position;
if(move!=null || back!=null) {
move.setEnabled(false);
back.setEnabled(false);
}
Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
if(getRequestedOrientation()==ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
imageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(), msg.what,100,100));
else imageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(), msg.what,400,400)); // OUT OF MEMORY ERROR
}
};
handler.sendEmptyMessage(image);
getSupportActionBar().setTitle(getResources().getString(R.string.title_how_to) + " " + name + ": " + (position+1)+"/"+(count));
if(position==0 || position+1==count){
if(position==0){
findViewById(R.id.backBtn).setEnabled(false);
findViewById(R.id.backBtn).setVisibility(View.INVISIBLE);
}
else {
findViewById(R.id.moveBtn).setEnabled(false);
findViewById(R.id.moveBtn).setVisibility(View.INVISIBLE);
Toast.makeText(getApplicationContext(),getString(R.string.finish),Toast.LENGTH_SHORT).show();
}
}
else {
showNavButtons();
}
if(move!=null || back!=null) {
move.setEnabled(true);
back.setEnabled(true);
}
2 методы из статьи Google:
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, 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/2;
final int halfWidth = width/2;
// 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;
}
Пожалуйста, не ругайтесь в своих ответах. – JAL
кажется, что вам нужно часто чистить/перестраивать проекты при работе с изображениями в приложении. Я включил 3 изображения в приложение (у них было ~ 1.5mb вместе), и приложение разбилось. Независимо от того, что я сделал (мне удалось уменьшить их размер до 50kb), это не помогло. После того, как я очистил/перестроил проект, все внезапно сработало (с меньшими изображениями c). Я предполагаю, что кэшированные изображения использовались перед чисткой/перестройкой, и, таким образом, на самом деле не имело значения, как я оптимизировал изображения. – vanomart