java - GridView内存不足位图

标签 java android memory gridview crash

所以我有一个问题,因为内存不足,我的应用程序崩溃了。

首先我的适配器代码确实有很多好的解决方案:

    public class ImageAdapter extends BaseAdapter {
    private Context mContext;

    // Keep all Images in array
    public Integer[] mThumbIds = {
            R.drawable.accidentally_open_internet_explorer,
            R.drawable.angry_shaking,                               R.drawable.are_you_fucking_kidding_me, 
            R.drawable.angry_with_pc,
            R.drawable.sample_7,                                R.drawable.awkward_moment,
            R.drawable.awkward_moment,                          
            R.drawable.beer_guy,                                
                                        R.drawable.beng,
            R.drawable.accidentally_open_internet_explorer,     R.drawable.boobs,
            R.drawable.big_smile,                               R.drawable.cereal_guy,
            R.drawable.challenge_accepted_drunk,                            R.drawable.challenge_accepted,
            R.drawable.bad_pokerface,                           R.drawable.challenge_considered,
            R.drawable.challenge_denied,                            R.drawable.challenge_failed,
            R.drawable.classic_rage,                                    R.drawable.one_does_not_simply,
            R.drawable.computer_stare,                  R.drawable.computer_slice,
            R.drawable.concentrated,                    R.drawable.concentrate,
            R.drawable.concentrated_teeth,                      R.drawable.cry_pc,
            R.drawable.dat_ass,                                 R.drawable.desk_flip,
            R.drawable.double_facepalm,                                 R.drawable.duck_yeah,
            R.drawable.fap,                                 R.drawable.fap_accepted,
            R.drawable.fap_gentleman,                               R.drawable.feels_good_man,
            R.drawable.forever_a_gamer,                                 R.drawable.forever_alone_clean,
            R.drawable.forever_alone_sad,                               R.drawable.forever_alone_together,
            R.drawable.fuck_that_bitch_yao_pff,                                 R.drawable.fuck_that_yao_ming,
            R.drawable.fuck_yeah,                       R.drawable.fuck_yeah_close_enough,
            R.drawable.gentleman_troll,                                 R.drawable.happy_smoking,
            R.drawable.haters_gonna_hate,                           R.drawable.if_you_know_what_i_mean_mr_bean,
            R.drawable.if_you_know_what_i_mean_mr_bean_blank,                           R.drawable.if_you_know_what_i_mean_mr_bean_blank,
            R.drawable.impossibru,                          R.drawable.indeed,
            R.drawable.jesus,                                   R.drawable.keyboard_break,
            R.drawable.knowthatfeel,                    R.drawable.like_a_sir,
            R.drawable.long_long_neck_surprise,                     R.drawable.look_from_bottom,
            R.drawable.me_gusta,                        R.drawable.me_gusta_creepy,
            R.drawable.me_gusta_makeup,                                 R.drawable.not_sure_if_gusta,
            R.drawable.now_kiss,                                R.drawable.one_does_not_simply,
            R.drawable.sample_1,                                R.drawable.sample_4,
            R.drawable.sample_7,                                R.drawable.sample_12,
            R.drawable.sample_13,                               R.drawable.today_is_monday,
            R.drawable.trees_smile,                                 R.drawable.trees_stoned,
            R.drawable.trees_stoned_exhale,                                 R.drawable.trees_stoned_inhale,
            R.drawable.wonka,                               R.drawable.y_u_no,
            R.drawable.yea_science,                                 R.drawable.you_are_the_man


    };


    // Constructor
    public ImageAdapter(Context c){
        mContext = c;
    }

    @Override
    public int getCount() {
        return mThumbIds.length;
    }

    @Override
    public Object getItem(int position) {
        return mThumbIds[position];
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)

.....

然后我尝试了2解决方案:
First:

    public View getView(int position, View convertView, ViewGroup parent) {
    //This actually is a bad solution, because every time convertView is reused, you will still initialize new ImageView, which is wrong
    //ImageView imageView = new ImageView(this.mContext);
    //new BitmapWorkerTask(imageView).execute(Tattoos[position]);
    //return imageView;

    //Better solution
    ImageView imageView = null;

    if (convertView == null) {
        imageView = new ImageView(this.mContext);
        new BitmapWorkerTask(imageView).execute(Tattoos[position]);
        //create new ImageView if it is not present and populate it with some image
    } else {
        imageView = (ImageView) convertView;
        //re-use ImageView that already exists in memory
    }

return imageView;
}


class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
        private final WeakReference<ImageView> imageViewReference;
        private int data = 0;

        public BitmapWorkerTask(ImageView imageView) {
            // Use a WeakReference to ensure the ImageView can be garbage collected
            imageViewReference = new WeakReference<ImageView>(imageView);
        }

        // Decode image in background.
        @Override
        protected Bitmap doInBackground(Integer... params) {
            data = params[0];
            return decodeSampledBitmapFromResource(ImageAdapter.this.mContext.getResources(), data, 100, 100);
        }

        // Once complete, see if ImageView is still around and set bitmap.
        @Override
        protected void onPostExecute(Bitmap bitmap) {
            if (imageViewReference != null && bitmap != null) {
                final ImageView imageView = imageViewReference.get();
                if (imageView != null) {
                    imageView.setImageBitmap(bitmap);
                    imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
                    imageView.setLayoutParams(new GridView.LayoutParams(100, 70));
                }
            }
        }
    }

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

            // Calculate ratios of height and width to requested height and width
            final int heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);

            // Choose the smallest ratio as inSampleSize value, this will guarantee
            // a final image with both dimensions larger than or equal to the
            // requested height and width.
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }

        return inSampleSize;
    }

}

但是我的问题是这些图片彼此重叠,所以它们彼此重叠,为什么???

2解决方案:
@Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ImageView imageView = new ImageView(mContext);
        //  TextView txt = new TextView(mContext);
        imageView.setImageResource(mThumbIds[position]);
        imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
        imageView.setLayoutParams(
              new  GridView.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, 
                 RelativeLayout.LayoutParams.WRAP_CONTENT));   
         Bitmap m_d = BitmapFactory.decodeResource(mContext.getResources(), 
                                           mThumbIds[position]);
        if (m_d != null)
        {
             Bitmap resizedBitmap = Bitmap.createScaledBitmap(m_d, 205, 205, true);
             imageView.setImageBitmap(resizedBitmap);
        };
        return imageView;}}

但这太迟了,为什么呢???

谢谢您的帮助!

最佳答案

每当使用BitmapFactory创建位图时,必须确保在完成该位图实例后调用.recycle(),否则很快就会耗尽内存。

您的第一个解决方案更接近正确,因为您需要回收那些convertView对象,因此只需确保您的convertView存在,并且在创建新的bitmap之前,您已经回收了它可能已经保留的所有位图。

public View getView(int position, View convertView, ViewGroup parent) {

    ImageView imageView = null;

    if (convertView == null) {
        imageView = new ImageView(this.mContext);
    } else {
        imageView = (ImageView) convertView;
    }

    // clean up your old bitmap first, if there is one.
    if(imageView.getDrawable() instanceof BitmapDrawable){
        BitmapDrawable bd = (BitmapDrawable) imageView.getDrawable();
        imageView.setDrawable(null);
        if(bd.getBitmap() != null){
            bd.getBitmap().recycle();
        }
        bd = null;
    }

    new BitmapWorkerTask(imageView).execute(Tattoos[position]);


    return imageView;
}

关于java - GridView内存不足位图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22693590/

相关文章:

r - 如何避免R中的内存限制

java - 适用于 Java Dev 2019-09 的 Oracle Eclipse IDE Windowbuilder 使 IDE 崩溃

java - 从不同的类访问方法

android - 如何在android中动态高效地切换activity?

java - 从 Java 迁移到 Android

iphone - 应用程序崩溃,但仅在为 Ad-Hoc 发行版构建时

java - 更改项目方面后无法运行应用程序?

java - 如果初始化程序代码在方法之间拆分,双重检查锁惯用语是否安全?

android - 如何使用 adb pull 命令?

.net - "ContentPresenter.Content"内存泄漏