【问题标题】:Android AsyncTask decode bitmap and set to imageAndroid AsyncTask 解码位图并设置为图像
【发布时间】:2012-11-05 13:48:52
【问题描述】:

我使用自定义方法解码位图并将其设置为 imageview 作为背景。目前它工作正常,但在某些设备中,有时它会由于内存不足错误而崩溃。知道如何优化该代码并使其变得更好吗?这是我正在使用的:

    class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
    private final WeakReference<ImageView> imageViewReference;
    private String data = null;

    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(String... params) {
        data = params[0];

        if(data != null){
            File bufferFile = new File(data);
            Log.e("","data : "+data);
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(bufferFile);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }

            Cipher cipher = null;
            try {
                cipher = Cipher.getInstance("AES/CBC/NoPadding");
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            }
            int userId = RPCCommunicator.getUserId(Store.this);
            String secretSalt = RPCCommunicator.getSecretKey(userId);
            String iv = RPCCommunicator.getIv(secretSalt);
            SecretKeySpec keySpec = new SecretKeySpec(secretSalt.getBytes(), "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes());
            try {
                cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (InvalidAlgorithmParameterException e) {
                e.printStackTrace();
            }
            CipherInputStream cis = new CipherInputStream(fis, cipher);

            BitmapFactory.Options o2 = new BitmapFactory.Options();
            //o2.inSampleSize=2;
            o2.inTempStorage = new byte[4*1024];

            int width = (int) RPCCommunicator.getPlaceHolderWidth(Store.this, 45);
            int height = (int) RPCCommunicator.getPlaceHolderHeight(Store.this, 25);

            Rect rect = new Rect();
            rect.inset(width, height);

            Bitmap finall = BitmapFactory.decodeStream(cis,rect,o2);
            if(finall != null){
                Bitmap bmp = Bitmap.createScaledBitmap(finall, width, height, true);
                return bmp;
            } else {
                return null;
            }
        }
        return null;
    }

    // Once complete, see if ImageView is still around and set bitmap.
    @Override
    protected void onPostExecute(Bitmap bitmap) {
        if (imageViewReference != null) {
            final ImageView imageView = imageViewReference.get();
            if(bitmap != null){
                if (imageView != null) {
                    Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.fadein);
                    imageView.startAnimation(animation);
                    imageView.setImageBitmap(bitmap);
                }
            } else {
                int width = (int) RPCCommunicator.getPlaceHolderWidth(Store.this, 45);
                int height = (int) RPCCommunicator.getPlaceHolderHeight(Store.this, 25);

                RelativeLayout.LayoutParams param = new RelativeLayout.LayoutParams(width, height);
                param.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
                param.rightMargin = 15;
                imageView.setBackgroundResource(R.drawable.placeholder);
                imageView.setLayoutParams(param);
            }
        }
    }
}

非常感谢任何想法/建议/帮助!

【问题讨论】:

    标签: android bitmap android-asynctask


    【解决方案1】:

    试试这个代码

    public static Bitmap decodeFile(File f,int WIDTH,int HIGHT){
            try {
                //Decode image size
                BitmapFactory.Options o = new BitmapFactory.Options();
                o.inJustDecodeBounds = true;
                BitmapFactory.decodeStream(new FileInputStream(f),null,o);
    
                //The new size we want to scale to
                final int REQUIRED_WIDTH=WIDTH;
                final int REQUIRED_HIGHT=HIGHT;
                //Find the correct scale value. It should be the power of 2.
                int scale=1;
                while(o.outWidth/scale/2>=REQUIRED_WIDTH && o.outHeight/scale/2>=REQUIRED_HIGHT)
                    scale*=2;
    
                //Decode with inSampleSize
                BitmapFactory.Options o2 = new BitmapFactory.Options();
                o2.inSampleSize=scale;
                return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
            }
                catch (FileNotFoundException e) {}
            return null;
        }
    

    这将在您传递宽度和高度时缩放位图..

    【讨论】:

      【解决方案2】:

      在使用您的位图之后并在为其分配另一个值之前使用bitmap.recycle()。您还可以在实际使用之前缩小位图。这是一个链接:https://stackoverflow.com/a/13226982/1117338

      还有一个建议:在发布问题之前请先搜索一下。这是很多人已经解决的老问题了。

      【讨论】:

      • 正如我在 bitmap.recycle() 之前在许多其他地方读到的那样;每次都不起作用。我的问题实际上与流有关,因为 AsyncTask 在我的应用程序中仅使用一次,但是流从一个到另一个的对话正在分配内存,并且在内存较少的设备中它可能会导致崩溃。这是我需要比缩放位图更多建议的地方。我已经用其他功能对其进行了缩放。
      • 我正要和vickey说同样的话。完成图像后使用 recycle() 是一个非常好的主意。位图分配变得非常讨厌,尤其是在 2.x
      • 你所说的“从一个流到另一个流的对话”是什么意思?
      猜你喜欢
      • 1970-01-01
      • 2011-06-23
      • 1970-01-01
      • 2015-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-04
      • 1970-01-01
      相关资源
      最近更新 更多