滚动GridView会导致GC_FOR_ALLOC免费问题

时间:2015-11-20 03:38:19

标签: java android memory gridview scroll

我有一个内部有一些图像的gridview。有时当我滚动时,GC_FOR_ALLOC或堆增加了,我不知道为什么。我使用一种方法来加载最小化的图像。

我可以使用Picasso或ViewHolder吗? RecyclerView?

当我在我的个人设备上测试我的应用程序时,内存问题发生了一两次,尽管一切都还在运行。但是在较旧的智能手机上(效率较低),内存问题完全阻止了手机和其他应用的运行。

我在“setTag”上看到警告,好像问题是由内存泄漏引起的。

如何修复内存问题?

MainActivity.java

public class MainActivity extends Activity {
GridView gridView;
MediaPlayer mPlayer;

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

    boolean internetAcces = checkDataConnection();
    if(internetAcces == true){
        setContentView(R.layout.activity_main);
        AdView adView = (AdView) this.findViewById(R.id.adView);
        AdRequest adRequest1 = new AdRequest.Builder().build();
        adView.loadAd(adRequest1);
    }
    else{
        setContentView(R.layout.activity_main2);
    }
    gridView = (GridView)findViewById(R.id.gridview);
    gridView.setAdapter(new MyAdapter(this));
    gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() 
    {
            @Override
            public synchronized void onItemClick(AdapterView<?> parent, View view, int position, long id)
            {

                try{
                    if(mPlayer != null && mPlayer.isPlaying())
                    {
                        mPlayer.stop();
                        mPlayer.release();
                        playSong(position);
                    }
                    else
                    {
                        playSong(position);
                    }
                }catch(Exception ex){
                    //Toast.makeText(MainActivity.this, ex.getMessage(), Toast.LENGTH_SHORT).show();
                }

            }
    });


}

@Override
protected void onPause(){
    super.onPause();
}

@Override
protected void onStop() {
    super.onStop();
    System.exit(0);
}

@Override
protected void onDestroy(){
    super.onDestroy();
    System.exit(0);
}

这是MyAdapter.java

public final class MyAdapter extends BaseAdapter {
private final List<Item> mItems = new ArrayList<Item>(30);
private final LayoutInflater mInflater;
public Context context;

public MyAdapter(Context context) {
    mInflater = LayoutInflater.from(context);
    this.context = context;

    mItems.add(new Item("Hé pélo",       R.drawable.hepelo));
    mItems.add(new Item("Salut les losers",   R.drawable.salutleslosers));
    mItems.add(new Item("Arrête Abib", R.drawable.abib));
    mItems.add(new Item("Goût bite",      R.drawable.goutbite));
    mItems.add(new Item("Makassy",     R.drawable.makassy));
    mItems.add(new Item("Joris Lecon",      R.drawable.jorislecon));
    mItems.add(new Item("Cache la drogue",       R.drawable.cacheladrogue));
    mItems.add(new Item("Un peu trop tactile",   R.drawable.unpeutroptactile));
    mItems.add(new Item("Qui c'est qu'a touché à Dorian ?", R.drawable.dorian));
    mItems.add(new Item("T'es pas beau",      R.drawable.tespasbeau));
    mItems.add(new Item("Ta mère",     R.drawable.tamere));
    mItems.add(new Item("Je bute ce paquet de chips",     R.drawable.jebutecepaquetdechips));
    mItems.add(new Item("La maison du content",     R.drawable.lamaisonducontent));
    mItems.add(new Item("Mes péripétiiiiiies",     R.drawable.mesperipeties));
    mItems.add(new Item("La rapta babtou",     R.drawable.laraptababtou));
    mItems.add(new Item("Que vas-tu faire ?!",     R.drawable.bangbang));
    mItems.add(new Item("Oh les tétés !",     R.drawable.lestetes));
    mItems.add(new Item("Mollé mollé",     R.drawable.laraptababtou));
    mItems.add(new Item("Okéééé",     R.drawable.ok));
    mItems.add(new Item("Guillaume le thug",     R.drawable.guillaumelethug));
    mItems.add(new Item("C'est ma teub",     R.drawable.cestmateub));
    mItems.add(new Item("Je suis qu'un thug",     R.drawable.jsuisquunthug));
}

@Override
public int getCount() {
    return mItems.size();}

@Override
public Item getItem(int i) {
    return mItems.get(i);
}

@Override
public long getItemId(int i) {
    return mItems.get(i).drawableId;
}

@Override
public View getView(int i, View view, ViewGroup viewGroup) {
    View v = view;
    ImageView picture;
    TextView name;

    if (v == null) {
        v = mInflater.inflate(R.layout.grid_item, viewGroup, false);
        v.setTag(R.id.picture, v.findViewById(R.id.picture));
        v.setTag(R.id.text, v.findViewById(R.id.text));
    }

    picture = (ImageView) v.getTag(R.id.picture);

    name = (TextView) v.getTag(R.id.text);

    Item item = getItem(i);

    //picture.setImageResource(item.drawableId);
    picture.setImageBitmap(decodeSampledBitmapFromResource(context.getResources(),item.drawableId, 150, 150));

    name.setText(item.name);

    return v;}




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) {

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

private static class Item {
    public final String name;
    public final int drawableId;

    Item(String name, int drawableId) {
        this.name = name;
        this.drawableId = drawableId;
    }
}

}

main_activity.xml:

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<GridView
    android:id="@+id/gridview"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:layout_gravity="center"
    android:verticalSpacing="0dp"
    android:layout_weight="1"
    android:horizontalSpacing="0dp"
    android:stretchMode="columnWidth"
    android:numColumns="2"
    android:listSelector="@android:color/transparent"
    android:scrollingCache="false"
    android:animationCache="false"
 />

  <com.google.android.gms.ads.AdView
    android:id="@+id/adView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    ads:adSize="SMART_BANNER"
    ads:adUnitId="ca-app-pub-2373549811754777/2717783647" 
   />

grid_item.xml:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
         android:layout_height="match_parent">
<com.slamingresources.laboiteamisterv.SquareImageView
    android:id="@+id/picture"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scaleType="centerCrop"
    />

<TextView
    android:id="@+id/text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingLeft="10dp"
    android:paddingRight="10dp"
    android:paddingTop="4dp"
    android:paddingBottom="5dp"
    android:layout_gravity="bottom"
    android:textColor="@android:color/white"
    android:background="#55000002"
    />

Logcat:

11-20 03:21:45.878: I/dalvikvm-heap(16815): Clamp target GC heap from      128.451MB to 128.000MB
11-20 03:21:47.628: I/dalvikvm-heap(16815): Clamp target GC heap from 135.930MB to 128.000MB
11-20 03:21:47.688: D/dalvikvm(16815): GC_BEFORE_OOM freed 109065K, 85% free 20521K/131004K, paused 59ms, total 60ms
11-20 03:22:00.498: D/dalvikvm(16815): GC_FOR_ALLOC freed 3972K, 85% free 20494K/131004K, paused 24ms, total 24ms

2 个答案:

答案 0 :(得分:1)

我知道这已经过时了但对于那些仍在寻找相同答案的人:您可以使用getcachedir()暂时在Android中存储数据。

有关更多选项,请参阅Android data storage

答案 1 :(得分:0)

是的,你收到了这个错误!为什么? AFAIK,在Android 3.0之前(我完全不记得)位图不是自动recycle。不使用后必须回收位图。 要解决您的问题,建议您缓存Bitmap。当cached命中时,回收未使用的。
编辑:我认为解决问题的最简单方法是使用另一个库来帮助加载图像。你可以看看Universal ImageLoader。有一个功能可以帮助您加载目标大小:

// Load image, decode it to Bitmap and return Bitmap synchronously
ImageSize targetSize = new ImageSize(80, 50); // result Bitmap will be fit to this size
Bitmap bmp = imageLoader.loadImageSync(imageUri, targetSize, options);