2016-03-24 2 views
1

Im, использующий DisplayingBitmap.zip, загруженный с сайта разработчиков android для загрузки изображений асинхронно в изображение. Im получает base64 строки из webservice. поэтому изменил код, чтобы преобразовать base64 в bitmap в ImageFetcher.class из (DisplayingBitmaps) вместо загрузки изображения с URL-адреса.ImageView, показывающий черный/белый фон для прозрачного base64 string image

ПРИМЕЧАНИЕ: Im получение gif изображений в виде base64 строки.

Преобразование в растровое изображение base64

 public Bitmap convertBase64ToImage(String mBase64String) { 
      Bitmap bitmap = null; 
      try { 
       String imageDataBytes = mBase64String.substring(mBase64String.indexOf(",") + 1); 
       InputStream stream = new ByteArrayInputStream(Base64.decode(imageDataBytes.getBytes(), Base64.DEFAULT)); 
       bitmap = BitmapFactory.decodeStream(stream); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
      return bitmap; 
     } 
    } 

Преобразование base64 растрового изображения в файл Симметричного для получения декодированного уменьшенное растрового изображения с использованием метода processBitmap в ImageFetcher.class (DisplayingBitmaps):

/** 
     * The main process method, which will be called by the ImageWorker in the AsyncTask background 
     * thread. 
     * 
     * @param data The data to load the bitmap, in this case, a regular http URL 
     * @return The downloaded and resized bitmap 
     */ 
     private Bitmap processBitmap(String data, String imageID) { 
      if (BuildConfig.DEBUG) { 
       PrintLog.error(TAG, "processBitmap --- imageID " + imageID); 
      } 
      Bitmap bitmap = null; 
      bitmap = convertBase64ToImage(data); 
      if (bitmap != null) { 
       File f = null; 
       try { 
        //create a file to write bitmap data 
        f = new File(mContext.getFilesDir(), imageID); 
        f.createNewFile(); 

        //Convert bitmap to byte array 
        ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
        bitmap.compress(Bitmap.CompressFormat.PNG, 100/*ignored for PNG*/, bos); 
        byte[] bitmapdata = bos.toByteArray(); 

        //write the bytes in file 
        FileOutputStream fos = new FileOutputStream(f); 
        fos.write(bitmapdata); 
        fos.flush(); 
        fos.close(); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
       bitmap = decodeSampledBitmapFromFile(f.getAbsolutePath(), mImageWidth, mImageHeight, getImageCache()); 
      } 

      return bitmap; 
     } 

     @Override 
     protected Bitmap processBitmap(Object data, String imageID) { 
      return processBitmap(String.valueOf(data), imageID); 
     } 

decodeSampledBitmapFromFile метод из ImageResizer.class

public static Bitmap decodeSampledBitmapFromFile(String filename, int reqWidth, int reqHeight, ImageCache cache) { 
     // First decode with inJustDecodeBounds=true to check dimensions 
     final BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inJustDecodeBounds = true; 
     BitmapFactory.decodeFile(filename, options); 

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

     // If we're running on Honeycomb or newer, try to use inBitmap 
     if (DeviceUtils.hasHoneycomb()) { 
      addInBitmapOptions(options, cache); 
     } 

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

Реализация ImageFetcher.class (DisplayingBitmaps.zip) в моем классе

private static final String IMAGE_CACHE_DIR = "clubsCategoryIcons"; 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     ImageCache.ImageCacheParams cacheParams = new ImageCache.ImageCacheParams(getActivity(), IMAGE_CACHE_DIR); 
     cacheParams.setMemCacheSizePercent(0.25f); // Set memory cache to 10% of app memory 

     // The ImageFetcher takes care of loading images into our ImageView children asynchronously 
     mImageFetcher = new ImageFetcher(getActivity(), getResources().getDimensionPixelSize(R.dimen.image_icon_size)); 
     mImageFetcher.setLoadingImage(R.drawable.settings_clubs); 
     mImageFetcher.addImageCache(getActivity().getSupportFragmentManager(), cacheParams); 
    } 

передавая этот объект mImageFetcher в класс адаптера для загрузки изображений в асинхронном режиме для каждого элемента.

ClubsCategoryAdapter clubsAdapter = new ClubsCategoryAdapter(getActivity(), new ArrayList<ClubsCategoryParser.ClubsCategory>(), mImageFetcher); 
recyclerView.setAdapter(clubsAdapter); 

ClubsCategoryAdapter.class

public class ClubsCategoryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { 
private ImageFetcher mImageFetcher; 

public ClubsCategoryAdapter(Context context, ArrayList<ClubsCategoryParser.ClubsCategory> clubsCategoryList, ImageFetcher mImageFetcher) { 
     this.context = context; 
     this.clubsCategoryList = clubsCategoryList; 
     this.mImageFetcher = mImageFetcher; 
} 

@Override 
    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { 
     final ViewHolder viewHolder = (ViewHolder) holder; 
     final ClubsCategoryParser.ClubsCategory singleItem = clubsCategoryList.get(position); 
     if (!TextUtils.isNullOrEmpty(singleItem.image_url)) { 
       mImageFetcher.loadImage(singleItem.image_url, String.valueOf(singleItem.ID), viewHolder.imgCategoryIcon); 
      } 

метод LoadImage в ImageWorker.class (DisplayingBitmaps)

public void loadImage(Object data, String imageID, ImageView imageView) { 
     if (data == null) { 
      return; 
     } 

     BitmapDrawable value = null; 

     if (mImageCache != null) { 
      value = mImageCache.getBitmapFromMemCache(imageID); 
     } 

     if (value != null) { 
      // Bitmap found in memory cache 
      imageView.setImageDrawable(value); 
     } else if (cancelPotentialWork(data, imageView)) { 
      //BEGIN_INCLUDE(execute_background_task) 
      final BitmapWorkerTask task = new BitmapWorkerTask(data, imageID, imageView); 
      final AsyncDrawable asyncDrawable = new AsyncDrawable(mResources, mLoadingBitmap, task); 
      imageView.setImageDrawable(asyncDrawable); 
      // NOTE: This uses a custom version of AsyncTask that has been pulled from the 
      // framework and slightly modified. Refer to the docs at the top of the class 
      // for more info on what was changed. 
      task.executeOnExecutor(AsyncTask.DUAL_THREAD_EXECUTOR); 
      //END_INCLUDE(execute_background_task) 
     } 
    } 

фактическое AsyncTask для обработки изображения асинхронно

/** 
    * The actual AsyncTask that will asynchronously process the image. 
    */ 
    private class BitmapWorkerTask extends AsyncTask<Void, Void, BitmapDrawable> { 
     private Object mData; 
     private String imageID; 
     private final WeakReference<ImageView> imageViewReference; 

     public BitmapWorkerTask(Object data, String imageID, ImageView imageView) { 
      mData = data; 
      this.imageID = imageID; 
      imageViewReference = new WeakReference<ImageView>(imageView); 
     } 

     /** 
     * Background processing. 
     */ 
     @Override 
     protected BitmapDrawable doInBackground(Void... params) { 
      //BEGIN_INCLUDE(load_bitmap_in_background) 
      if (BuildConfig.DEBUG) { 
       PrintLog.error(TAG, "doInBackground - starting work"); 
      } 

      final String dataString = String.valueOf(mData); 
      Bitmap bitmap = null; 
      BitmapDrawable drawable = null; 

      // Wait here if work is paused and the task is not cancelled 
      synchronized (mPauseWorkLock) { 
       while (mPauseWork && !isCancelled()) { 
        try { 
         Log.e("pauseWork", "iswaiting -------------"); 
         mPauseWorkLock.wait(); 
        } catch (InterruptedException e) { 
        } 
       } 
      } 

      Log.e("pauseWork", "iswaiting end -------------"); 
      // If the image cache is available and this task has not been cancelled by another 
      // thread and the ImageView that was originally bound to this task is still bound back 
      // to this task and our "exit early" flag is not set then try and fetch the bitmap from 
      // the cache 
      if (mImageCache != null && !isCancelled() && getAttachedImageView() != null && !mExitTasksEarly) { 
       bitmap = mImageCache.getBitmapFromDiskCache(imageID); 
      } 

      // If the bitmap was not found in the cache and this task has not been cancelled by 
      // another thread and the ImageView that was originally bound to this task is still 
      // bound back to this task and our "exit early" flag is not set, then call the main 
      // process method (as implemented by a subclass) 
      if (bitmap == null && !isCancelled() && getAttachedImageView() != null && !mExitTasksEarly) { 
       bitmap = processBitmap(mData, imageID); 
      } 

      // If the bitmap was processed and the image cache is available, then add the processed 
      // bitmap to the cache for future use. Note we don't check if the task was cancelled 
      // here, if it was, and the thread is still running, we may as well add the processed 
      // bitmap to our cache as it might be used again in the future 
      if (bitmap != null) { 
       if (DeviceUtils.hasHoneycomb()) { 
        // Running on Honeycomb or newer, so wrap in a standard BitmapDrawable 
        drawable = new BitmapDrawable(mResources, bitmap); 
       } else { 
        // Running on Gingerbread or older, so wrap in a RecyclingBitmapDrawable 
        // which will recycle automagically 
        drawable = new RecyclingBitmapDrawable(mResources, bitmap); 
       } 

       if (mImageCache != null) { 
        mImageCache.addBitmapToCache(imageID, drawable); 
       } 
      } 

      if (BuildConfig.DEBUG) { 
       PrintLog.error(TAG, "doInBackground - finished work"); 
      } 

      return drawable; 
      //END_INCLUDE(load_bitmap_in_background) 
     } 

     /** 
     * Once the image is processed, associates it to the imageView 
     */ 
     @Override 
     protected void onPostExecute(BitmapDrawable value) { 
      //BEGIN_INCLUDE(complete_background_work) 
      // if cancel was called on this task or the "exit early" flag is set then we're done 
      if (isCancelled() || mExitTasksEarly) { 
       value = null; 
      } 

      final ImageView imageView = getAttachedImageView(); 
      if (value != null && imageView != null) { 
       if (BuildConfig.DEBUG) { 
        PrintLog.error(TAG, "onPostExecute - setting bitmap"); 
       } 
       setImageDrawable(imageView, value); 
      } 
      //END_INCLUDE(complete_background_work) 
     } 

     @Override 
     protected void onCancelled(BitmapDrawable value) { 
      super.onCancelled(value); 
      synchronized (mPauseWorkLock) { 
       mPauseWorkLock.notifyAll(); 
      } 
     } 

     /** 
     * Returns the ImageView associated with this task as long as the ImageView's task still 
     * points to this task as well. Returns null otherwise. 
     */ 
     private ImageView getAttachedImageView() { 
      final ImageView imageView = imageViewReference.get(); 
      final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); 

      if (this == bitmapWorkerTask) { 
       return imageView; 
      } 

      return null; 
     } 
    } 

Изображения показывают штраф в первый раз при установке приложения, но после убийства приложения и загружает ту же страница показывает изображение с черно/белым фоном.

Я пробовал много примеров и статей .. Но ничего не помогло. Я не знаю, почему это происходит с черно-белым фоном после убийства/выхода из приложения.

ответ

1

Ваше приложение показывает изображение в первый раз и отображает черный фон после повторного открытия приложения, потому что приложение «DisplayingBitmap» кэширует изображения в файловую систему с использованием формата JPEG. Как вы знаете, JPEG не поддерживает прозрачный режим.

Пожалуйста, откройте Imagecache класс и посмотреть на # 68 линии:

private static final CompressFormat DEFAULT_COMPRESS_FORMAT = CompressFormat.JPEG; 

Чтобы избежать черного фона, я изменил это значение в формате PNG:

private static final CompressFormat DEFAULT_COMPRESS_FORMAT = CompressFormat.PNG; 

UPDATE:

Кроме того, вы можете установить comp ressFormat to JPEG:

ImageCache.ImageCacheParams cacheParams = new ImageCache.ImageCacheParams(getActivity(), IMAGE_CACHE_DIR); 
     cacheParams.setMemCacheSizePercent(0.25f); 
cacheParams.compressFormat = Bitmap.CompressFormat.JPEG; 

это работает для меня и надеется, что это поможет вам.

Смежные вопросы