0

I'm new to android development and I'm a bit confused regarding decoding and scaling bitmaps using AsyncTask. I've read the android development site and it didn't help my understanding. My question is how exactly is this done? My goal is to decode and scale multiple images and placed them in ImageViews. Do I code the decoding and scaling within a doInBackground method? Any help will be great appreciated!

Hugo Gresse
  • 17,195
  • 9
  • 77
  • 119
Sean Dees
  • 47
  • 1
  • 3

3 Answers3

0

Yes, you should do anything you can on the doInBackground. Only when your image is ready than use "return" to call onPostExecute and in onPostExecute you should set the bitmap to the imageView.

roiberg
  • 13,629
  • 12
  • 60
  • 91
0

Do all the heavy loading stuff in the doInBackground method, and just set the image afterwards in the onPostExecute method.

Enable the strict mode (http://developer.android.com/reference/android/os/StrictMode.html) to make sure you have done everything right (will write a warning into your logcat in case you are doing something on the UI thread you shouldn't be doing):

 public void onCreate() {
     if (DEVELOPER_MODE) {
         StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                 .detectDiskReads()
                 .detectDiskWrites()
                 .detectNetwork()   // or .detectAll() for all detectable problems
                 .penaltyLog()
                 .build());
         StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                 .detectLeakedSqlLiteObjects()
                 .detectLeakedClosableObjects()
                 .penaltyLog()
                 .penaltyDeath()
                 .build());
     }
     super.onCreate();
 }

But I highly recommend to use a library like volley or Picasso whenever you are working with images from external sources. Take a look at the following question: Local image caching solution for Android: Square Picasso vs Universal Image Loader

Community
  • 1
  • 1
Lukas
  • 2,544
  • 2
  • 18
  • 33
0

This code sample is from my recipe app, and should illustrate what you are asking. The images are read in as base64 encoded data from a web service, so need to be decoded before they can be shown within a ListView.

The code first of all checks for cached images, if not it decodes them in the background using AsyncTask, and writes the result to cache for future use.

The decoding is done in doInBackground, and the display/write to cache is done in onPostExecute.

Hole this helps.

mRecipeAdapter = new ArrayAdapter<Recipe>(getActivity(), R.layout.listrow, mData2){
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                View row;

                if (null == convertView) {
                    row = mInflater.inflate(R.layout.recipe_listrow, null);
                } else {
                    row = convertView;
                }

                TextView tv = (TextView) row.findViewById(R.id.recipe_title);
                ImageView iv = (ImageView) row.findViewById(R.id.recipe_image);
                iv.setImageBitmap(null);

                Recipe r = getItem(position);       
                tv.setText(r.title);

                File cacheFile = new File(mCacheDir, ""+r.identity.hashCode());
                if (cacheFile.exists()){
                    FileInputStream fis;
                    try {
                        fis = new FileInputStream(cacheFile);
                        Bitmap bmp = BitmapFactory.decodeStream(fis); 
                        iv.setImageBitmap(bmp);
                        bmp = null;
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } 
                } else {
                    // Get image asynchronously from database
                    new AsyncImages(iv).execute(r);
                }

                return row;
            }


            class AsyncImages extends AsyncTask<Recipe, Void, Recipe> {

                private static final long MAX_SIZE = 5242880L; // 5MB

                private final WeakReference<ImageView> imageViewReference;

                public AsyncImages(ImageView imageView) {
                    imageViewReference = new WeakReference<ImageView>(imageView);
                }

                @Override
                protected Recipe doInBackground(Recipe... r) {
                    Recipe recipe = r[0];

                    double heapRemaining = Runtime.getRuntime().freeMemory(); //amount available in heap
                    Log.i("MEM REM", Double.toString(heapRemaining));
                    String imageString = SchwartzRecipesBaseActivity.getThumbnailImageFor(recipe.identity);
                    recipe.thumb = StringToBitMap(imageString);
                    imageString = null;

                    return recipe;
                }

                protected void onPostExecute(Recipe r) {
                    if (isCancelled()) {
                        r.thumb = null;
                        return;
                    }

                    if (imageViewReference != null) {
                        ImageView imageView = imageViewReference.get();
                        if (imageView != null) {
                            imageView.setImageBitmap(r.thumb);

                            // Write to cache file
                            // Make space if needed
                            long sz = getDirSize();
                            if (sz>MAX_SIZE){
                                makeSomeSpace(r.thumb.getByteCount());
                            }

                            File cacheFile = new File(mCacheDir, ""+r.identity.hashCode());
                            try {      
                                // Create a file at the file path, and open it for writing obtaining the output stream
                                cacheFile.createNewFile();       
                                FileOutputStream fos = new FileOutputStream(cacheFile); 
                                // Write the bitmap to the output stream (and thus the file) in PNG format (lossless compression)     
                                r.thumb.compress(CompressFormat.JPEG, 100, fos);
                                // Flush and close the output stream       
                                fos.flush();       
                                fos.close();
                            } catch (Exception e) {
                                // Log anything that might go wrong with IO to file      
                                Log.e("CACHE", "Error when saving image to cache. ", e);     
                            }  

                        }
                    }
                }

                private void makeSomeSpace(long bytes) {

                    long bytesDeleted = 0;
                    File[] files = mCacheDir.listFiles();

                    Arrays.sort(files, new Comparator<File>(){
                        public int compare(File f1, File f2)
                        {
                            return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified());
                        } });

                    for (File file : files) {
                        bytesDeleted += file.length();

                        file.delete();

                        if (bytesDeleted >= bytes) {
                            break;
                        }
                    }
                }

                private long getDirSize() {
                    if (mCacheDir == null) return 0;
                    long size = 0;
                    File[] files = mCacheDir.listFiles();

                    for (File file : files) {
                        if (file.isFile()) {
                            size += file.length();
                        }
                    }

                    return size;
                }
            }
            private Bitmap StringToBitMap(String encodedString) {
                try{
                  byte [] encodeByte=Base64.decode(encodedString,Base64.DEFAULT);
                  Bitmap bitmap=BitmapFactory.decodeByteArray(encodeByte, 0, encodeByte.length);
                  return bitmap;
                }catch(Exception e){
                  e.getMessage();
                  return null;
                }
            }
        };
        setListAdapter(mRecipeAdapter);
markt
  • 903
  • 7
  • 21