Android AsyncTask解码位图并设置为图像

时间:2012-11-05 13:48:53

标签: android bitmap android-asynctask

使用自定义方法解码位图并将其设置为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);
            }
        }
    }
}

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

2 个答案:

答案 0 :(得分:3)

试试这段代码

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

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

答案 1 :(得分:1)

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

另外一条建议:请在发布问题前仔细搜索。这是许多人已经解决的老问题。