Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
200 views
in Technique[技术] by (71.8m points)

bitmap - Android: Calling AsyncTask.execute() crashes the app

I have an activity where I load an image from the given URI. The android training article suggested that it should be done in background so that it does not block the UI. I followed the same Article.

Here is the snippet where I call the AsyncTask

    Uri uri = ....
    ImageLoaderTask task = new ImageLoaderTask(imageView);
    task.execute(uri);

My ImageLoaderTask is given below.

public class ImageLoaderTask extends AsyncTask<Uri, Void, Bitmap> {

private WeakReference<ImageView> imageViewReference;

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

@Override
protected Bitmap doInBackground(Uri... params) {
    Bitmap bitmap = ImageUtils
                .decodeSampledBitmapFromFile(params[0], 200,
                        200);
    return bitmap;
}

@Override
protected void onPostExecute(Bitmap bitmap) {
    if (imageViewReference != null && bitmap != null) {
            final ImageView imageView = imageViewReference.get();
            if (imageView != null) {
                imageView.setImageBitmap(bitmap);
            }
        }
}

}

This is almost as described in the article specified above.

The code in ImageUtils class is given below

public static Bitmap decodeSampledBitmapFromFile(Uri uri,
                                                 int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        File imageFile = getImageFile(uri);
        BitmapFactory.decodeFile(imageFile.getPath(), options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(imageFile.getPath(), options);

}

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

When I call the task.execute(uri), the app crashes. I tried it in my phone and not on the emulator. I could not get my emulator running on my machine since it takes too much time.

What could be the possible cause of this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Instead of passing ImaageView reference to Async class standard practice try to define custom interface for load bitmap

public interface ImageBitampLoadListener {
    public void onBitampLoad(Bitmap bitmap);
}

Pass custom interface reference Async :

private ImageBitmapLoadListener listener;

public ImageLoaderTask(ImageBitmapLoadListener listener) {
    this.listener = listener;
}

Set call back from Async :

@Override
protected void onPostExecute(Bitmap bitmap) {
   super.onPostExecute(bitmap);
   if(listener!=null){
      listener.onBitampLoad(bitmap);
   }
}

Set custom listener to Async and get Bitamp :

ImageLoaderTask task = new ImageLoaderTask(new ImageBitmapLoadListener() {
    @Override
    public void onBitampLoad(Bitmap bitmap) {
         imageView.setImageBitmap(bitmap);
    }
});
task.execute(uri);

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...