Ленивое загрузочное изображение с индикатором выполнения делает повреждение изображения при отображении изображения

У меня есть приложение, отображающее изображения с сервера. Теперь я лениво загружаю свои изображения. Поэтому изначально я показываю индикатор выполнения при загрузке изображения. Я View.INVISIBLE индикатор выполнения, устанавливая его атрибут visibility в View.INVISIBLE и изображение появляется. Это файл макета, который я использую для изображений

 <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="center" > <ImageView android:id="@+id/imageView1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="center" android:contentDescription="@string/app_name" android:scaleType="centerInside" android:src="@drawable/ic_launcher" /> <RelativeLayout android:id="@+id/loading_layout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@android:color/white" > <ProgressBar android:id="@+id/progressBar1" style="?android:attr/progressBarStyleSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:background="@android:color/white" /> </RelativeLayout> </FrameLayout> 

Проблема Когда индикатор выполнения исчезнет, ​​изображение отображается на экране, но повреждено. Как это изображение

Когда я обновляю список изображений, загруженных из каталога кеша, и когда они отображаются на экране, они отображаются корректно без какого-либо повреждения.

Введите описание изображения здесь

Класс ImageLoader i используется для ленивого изображения загрузки

 public class ImageLoader { // @@ JUST FOR THIS PROJECT BaseAdapter mAdapter; // @@ MemoryCache memoryCache = new MemoryCache(); FileCache fileCache; private Map<ImageView, String> imageViews = Collections .synchronizedMap(new WeakHashMap<ImageView, String>()); ExecutorService executorService; boolean addRoundCournerAndStroke = false; boolean scale = false; boolean localfile = false; int default_image; public ImageLoader(Context context, boolean flag, boolean scale, boolean localfile) { fileCache = new FileCache(context); this.addRoundCournerAndStroke = flag; executorService = Executors.newFixedThreadPool(5); this.scale = scale; this.localfile = localfile; } public ImageLoader(Context context, boolean flag, boolean scale, boolean localfile, int default_image_id) { this(context, flag, scale, localfile); this.default_image = default_image_id; } public ImageLoader(Context context, boolean flag, boolean scale, boolean localfile, int default_image_id, BaseAdapter adapter) { this(context, flag, scale, localfile); this.default_image = default_image_id; this.mAdapter = adapter; } public void DisplayImage(String url, ImageView imageView) { imageViews.put(imageView, url); Bitmap bitmap = memoryCache.get(url); if (bitmap != null) { changeProgressBarVisibilty(imageView, false); imageView.setImageBitmap(bitmap); } else { queuePhoto(url, imageView); imageView.setImageResource(this.default_image); } } private void queuePhoto(String url, ImageView imageView) { PhotoToLoad p = new PhotoToLoad(url, imageView); executorService.submit(new PhotosLoader(p)); } private Bitmap getBitmap(String url) { File f = null; if (localfile) f = new File(url); else f = fileCache.getFile(url); // Log.d("bytes", "decode"); // from SD cache Bitmap b = decodeFile(f); if (b != null) return b; // from web try { Bitmap bitmap = null; URL imageUrl = new URL(url); HttpURLConnection conn = (HttpURLConnection) imageUrl .openConnection(); conn.setConnectTimeout(30000); conn.setReadTimeout(30000); conn.setInstanceFollowRedirects(true); InputStream is = conn.getInputStream(); OutputStream os = new FileOutputStream(f); Utils.CopyStream(is, os); os.close(); bitmap = decodeFile(f); // //Log.d("bytes", "decode"); return bitmap; } catch (Exception ex) { ex.printStackTrace(); return null; } } private Bitmap decodeFileWithoutScaling(File f) { try { BitmapFactory.Options o2 = new BitmapFactory.Options(); o2.inSampleSize = 1; //o2.inPurgeable = true; if (this.localfile) return BitmapFactory.decodeFile(f.getAbsolutePath(), o2); else return BitmapFactory.decodeStream(new FileInputStream(f), null, o2); } catch (FileNotFoundException e) { } return null; } private Bitmap decodeFile(File f) { if (this.scale) { return decodeFileWithScalling(f); } else { return decodeFileWithoutScaling(f); } } // decodes image and scales it to reduce memory consumption private Bitmap decodeFileWithScalling(File f) { try { // decode image size BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; // o.inPurgeable = true; if (this.localfile) BitmapFactory.decodeFile(f.getAbsolutePath(), o); else BitmapFactory.decodeStream(new FileInputStream(f), null, o); // Find the correct scale value. It should be the power of 2. final int REQUIRED_SIZE = 70; int width_tmp = o.outWidth, height_tmp = o.outHeight; // Log.d("width", width_tmp + ""); // Log.d("height", height_tmp + ""); int scale = 1; while (true) { if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE) break; width_tmp /= 2; height_tmp /= 2; scale *= 2; } // decode with inSampleSize BitmapFactory.Options o2 = new BitmapFactory.Options(); o2.inSampleSize = scale; // o2.inPurgeable = true; // Log.d("after shave width", o2.outWidth + ""); // Log.d("after shave height", o2.outHeight + ""); if (this.localfile) return BitmapFactory.decodeFile(f.getAbsolutePath(), o2); else return BitmapFactory.decodeStream(new FileInputStream(f), null, o2); } catch (FileNotFoundException e) { } return null; } // Task for the queue private class PhotoToLoad { public String url; public ImageView imageView; public PhotoToLoad(String u, ImageView i) { url = u; imageView = i; } } class PhotosLoader implements Runnable { PhotoToLoad photoToLoad; PhotosLoader(PhotoToLoad photoToLoad) { this.photoToLoad = photoToLoad; } public void run() { if (imageViewReused(photoToLoad)) { return; } Bitmap bmp = getBitmap(photoToLoad.url); // if (addRoundCournerAndStroke) { // // bmp = ImageHelper.rotateAndFrame(bmp, 10); // bmp = ImageHelper.getRoundedCornerBitmap(bmp, 10); // } memoryCache.put(photoToLoad.url, bmp); if (imageViewReused(photoToLoad)) return; BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad); Activity a = (Activity) photoToLoad.imageView.getContext(); a.runOnUiThread(bd); } } boolean imageViewReused(PhotoToLoad photoToLoad) { String tag = imageViews.get(photoToLoad.imageView); if (tag == null || !tag.equals(photoToLoad.url)) return true; return false; } // Used to display bitmap in the UI thread class BitmapDisplayer implements Runnable { Bitmap bitmap; PhotoToLoad photoToLoad; public BitmapDisplayer(Bitmap b, PhotoToLoad p) { bitmap = b; photoToLoad = p; } public void run() { if (imageViewReused(photoToLoad)) return; changeProgressBarVisibilty(photoToLoad.imageView, false); if (bitmap != null) { photoToLoad.imageView.setImageBitmap(bitmap); } else { photoToLoad.imageView .setImageResource(ImageLoader.this.default_image); } if (mAdapter != null) { mAdapter.notifyDataSetChanged(); } } } private void changeProgressBarVisibilty(ImageView image, boolean visible) { ViewGroup layout = (ViewGroup) image.getParent(); try { View v = layout.findViewById(R.id.loading_layout); v.setVisibility(visible ? View.VISIBLE : View.GONE); } catch (Exception ex) { ex.printStackTrace(); } } public void clearCache() { memoryCache.clear(); fileCache.clear(); } } 

Попробуйте использовать ProgressDialog вместо Progressbar. ProgressDialog также может использовать индикатор выполнения. ProgressDialog не является типом XML. Поэтому вы можете показать () или отклонить () метод. Возможно, это не проблема. Я думаю, что эта проблема исходит от RelativeLayout. Если вы используете ProgressBar Visiblity, RelativeLayout все еще остается видимым (но не имеет фона). Также RelativeLayout имеет любой элемент. Я предполагаю, что Пустой макет дал вам коррупцию. Лучше всего использовать ProgressDialog.

Поврежденное изображение показывает поврежденные артефакты JPEG.

Ваша проблема может возникнуть из метода BitmapFactory.decodeStream . Не все JPEG-файлы оптимизированы для декодирования на лету («прогрессивные»), поэтому они, возможно, должны быть доступны в целом до правильного декодирования. Обычно прогрессивные изображения могут быть декодированы сверху вниз, но это, возможно, не выполняется для всех файлов, или декодер может иметь некоторые недостатки, которые мешают этому.

С другой стороны, если изображение затем извлекается из кэшированного файла, используется BitmapFactory.decodeFile который не нуждается в заботе о потоковых данных и может случайно получить доступ к файлу изображения для декодирования JPEG. Если вам не нужны потоковые обновления дисплея при загрузке изображения, я бы предложил установить этот путь кода и всегда загружать все изображение перед декодированием.

Я думаю, вы можете попытаться установить видимость как View.GONE , потому что когда вы устанавливаете View.INVISIBLE View по-прежнему занимает место, и, как сказал Tae, это могут быть некоторые проблемы с RelativeLayout.

ура