“OutOfMemoryError”在ListView中滚动图像时

时间:2016-10-17 04:33:05

标签: java android android-bitmap

10-16 21:49:03.318 29852-29852/com.klau.jobsinaustralia I/dalvikvm-heap: Grow heap (frag case) to 171.874MB for 14400016-byte allocation
10-16 21:49:03.578 29852-29852/com.klau.jobsinaustralia I/dalvikvm-heap: Grow heap (frag case) to 175.314MB for 14400016-byte allocation
10-16 21:49:03.689 29852-29852/com.klau.jobsinaustralia I/dalvikvm-heap: Grow heap (frag case) to 177.603MB for 3600016-byte allocation
10-16 21:49:03.839 29852-29852/com.klau.jobsinaustralia I/dalvikvm-heap: Grow heap (frag case) to 178.716MB for 14364016-byte allocation
10-16 21:49:04.029 29852-29852/com.klau.jobsinaustralia I/dalvikvm-heap: Grow heap (frag case) to 182.185MB for 14400016-byte allocation
10-16 21:49:04.139 29852-29852/com.klau.jobsinaustralia I/dalvikvm-heap: Forcing collection of SoftReferences for 3600016-byte allocation
10-16 21:49:04.199 29852-29852/com.klau.jobsinaustralia E/dalvikvm-heap: Out of memory on a 3600016-byte allocation.
10-16 21:49:04.199 29852-29852/com.klau.jobsinaustralia I/dalvikvm: "main" prio=5 tid=1 RUNNABLE
10-16 21:49:08.223 29852-29852/com.klau.jobsinaustralia E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.OutOfMemoryError: (Heap Size=194912KB, Allocated=182627KB)
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:628)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:475)
at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:504)
at com.klau.jobsinaustralia.scrollable.CustomList.decodeSampledBitmapFromResource

活动

public class ExtraInfoActivity extends BaseActivity {

ListView list;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
    final String languageToLoad = sharedPreferences.getString("PREF_LIST", "no selection");
    Locale locale = new Locale(languageToLoad);
    Locale.setDefault(locale);
    Configuration config = new Configuration();
    config.locale = locale;
    getBaseContext().getResources().updateConfiguration(config,getBaseContext().getResources().getDisplayMetrics());

    setContentView(R.layout.activity_extra_info);
    String[] nsw_attraction = {
            "Sydney Bridge",
            "Blue Mountains",
            "Bondi Beach",
            "The Hunter Valley",
            "The Jenolan Caves"
    };


    final String[] nsw_web = {
            getResources().getString(R.string.nsw_attraction_1),
            getResources().getString(R.string.nsw_attraction_2),
            getResources().getString(R.string.nsw_attraction_3),
            getResources().getString(R.string.nsw_attraction_4),
            getResources().getString(R.string.nsw_attraction_5)
    };

    Integer[] nswImageId = {
            R.drawable.nsw_attraction_bridge,
            R.drawable.nsw_attraction_blue_mountains,
            R.drawable.nsw_attraction_bondi_beach,
            R.drawable.nsw_attraction_hunter_valley,
            R.drawable.nsw_attraction_jenolan_caves
    };
    CustomList adapter = new CustomList(ExtraInfoActivity.this, nsw_attraction, nsw_web, nswImageId);
    list = (ListView) findViewById(R.id.list);
    list.setAdapter(adapter);
    list.setOnItemClickListener(new AdapterView.OnItemClickListener() {        
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Toast.makeText(ExtraInfoActivity.this, nsw_web[+position], Toast.LENGTH_SHORT).show();
        }
    });
}

@Override
public void onStart() {
    super.onStart();
    try {
        mTracker.setScreenName("Extra Infomation");
        mTracker.send(new HitBuilders.AppViewBuilder().build());
    }catch (Exception ex){
        ex.printStackTrace();
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_home, menu);
    return true;
}

}

5 个答案:

答案 0 :(得分:0)

我已经调整了图像的大小。我的CustomList类

公共类CustomList扩展了ArrayAdapter {

private final Activity context;
private final String[] placeName;
private final String[] web;
private final Integer[] imageId;

public CustomList(Activity context, String[] placeName,  String[] web, Integer[] imageId) {
    super(context, R.layout.list_single, web);
    this.context = context;
    this.placeName = placeName;
    this.web = web;
    this.imageId = imageId;

}
@Override
public View getView(int position, View view, ViewGroup parent) {

    LayoutInflater inflater = context.getLayoutInflater();
    View rowView= inflater.inflate(R.layout.list_single, null, true);


    TextView place = (TextView) rowView.findViewById(R.id.place_name);
    place.setText(placeName[position]);
    TextView txtTitle = (TextView) rowView.findViewById(R.id.txt);
    txtTitle.setText(web[position]);

    ImageView imageView = (ImageView) rowView.findViewById(R.id.img);

    Bitmap bitmap = decodeSampledBitmapFromResource(context.getResources(), imageId[position], 150, 150);
    if (bitmap != null) {
      bitmap.recycle();    //<====== ERROR here: java.lang.IllegalArgumentException: Cannot draw recycled bitmap.
    }
    imageView.setImageBitmap(bitmap);
    return rowView;
}

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

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
                                                     int reqWidth, int reqHeight) {

    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    options.inJustDecodeBounds = false;

    return BitmapFactory.decodeResource(res, resId, options);

}

}

答案 1 :(得分:0)

您需要使用库来加载ListView

中的图像

Glide是一个用于加载图像的神奇库。

它的设置非常简单:

将这两个放在build.gradle

dependencies {
    compile 'com.github.bumptech.glide:glide:3.7.0'
    compile 'com.android.support:support-v4:19.1.0'
}

然后在您的适配器中,您需要做的就是:

Glide
    .with(context)
    .load(nswImageId[position])
    .into(myImageView);

就是这样,它将照顾一切。您可以找到更多信息和使用详情here

答案 2 :(得分:0)

使用 Picasso Library 。它易于使用并且还可以处理许多其他错误。 http://square.github.io/picasso/

答案 3 :(得分:0)

非常感谢你的快速回答。不确定我能做得对吗请重新审视我的更改。

@Override
public View getView(int position, View view, ViewGroup parent) {
    final ImageView myImageView;

    LayoutInflater inflater = context.getLayoutInflater();
    View rowView= inflater.inflate(R.layout.list_single, null, true);

    TextView place = (TextView) rowView.findViewById(R.id.place_name);
    place.setText(placeName[position]);
    TextView txtTitle = (TextView) rowView.findViewById(R.id.txt);
    txtTitle.setText(web[position]);

    ImageView imageView = (ImageView) rowView.findViewById(R.id.img);

    if (view == null) {
        myImageView = (ImageView) inflater.inflate(imageView, parent, false);
    } else {
        myImageView = (ImageView) recycled;
    }


    Glide
        .with(context)
        .load(nswImageId[position])
        .into(myImageView);     

    return myImageView;
}

答案 4 :(得分:0)

将此行写在清单文件

中的应用程序标记中
  android:largeHeap="true"