2012-07-26 1 views
12

Ich habe eine Anwendung, die Bilder von Server angezeigt. Jetzt lade ich meine Bilder faul. so zunächst ich einen Fortschrittsbalken anzeigen, wenn das Bild fertig Laden ich den Fortschrittsbalken entfernen, indem Sie visibility Attribut auf View.INVISIBLE Attribut setzen und das Bild erscheint. Dies ist die Layout-Datei i für Bilder verwendenLazy laden Bild mit Fortschrittsbalken machen Bildbeschädigung, wenn das Bild angezeigt

<?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> 

Das Problem Wenn der Fortschrittsbalken das Bild auf dem Bildschirm angezeigt werden, verschwinden aber beschädigt. wie dieses Bild

wenn ich die Liste aktualisieren die Bilder aus dem Cache-Verzeichnis geladen und wenn sie auf dem Bildschirm angezeigt werden sie korrekt angezeigt, ohne jegliche Beschädigung.

enter image description here

Imageloader-Klasse i verwenden, um faul Last Bild

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

} 
+2

Versuchen Sie die [Universal Image Loader] (https://github.com/nostra13/Android-Universal-Image-Loader) Bibliothek zum Laden von Bildern zu verwenden. Vielleicht hat es dieses Problem nicht. – NOSTRA

+0

Anstatt die Fortschrittsleiste auszublenden, wenn das Bild geladen wird, machen Sie die Bildansicht sichtbar. Verstecken Sie es, bevor Sie anfangen zu laden ... – Ronnie

Antwort

5

Try ProgressDialog statt Progressbar zu verwenden. ProgressDialog kann auch Fortschrittsbalken verwenden. ProgressDialog ist kein XML-Typ. Sie können also die Methode show() oder abweisen() verwenden. Vielleicht hat es dieses Problem nicht. Ich denke, dieses Problem kommt von RelativeLayout. Wenn Sie ProgressBar Visiblity verwenden, ist RelativeLayout immer noch sichtbar (hat aber keinen Hintergrund). RelativeLayout hat auch einen Gegenstand. Ich schätze, leeres Layout hat dir Korruption gebracht. ProgressDialog Verwendung ist am besten ..

-1

Ich glaube, Sie können versuchen, die Sichtbarkeit als View.GONE zu setzen, denn wenn man View.INVISIBLE die Ansicht immer noch den Platz hält gesetzt, und wie Tae sagte, es kann einige Probleme mit RelativeLayout sein.

Prost

3

Das beschädigte Bild zeigt beschädigte JPEG-Artefakte.

Ihr Problem kann sich aus der BitmapFactory.decodeStream Methode ergeben. Nicht alle JPEGs sind für die direkte Dekodierung ("progressive") optimiert, so dass sie möglicherweise als Ganzes verfügbar sein müssen, bevor sie korrekt decodiert werden. Normalerweise können nicht-progressive Bilder von oben nach unten decodiert werden, aber das gilt möglicherweise nicht für alle Dateien oder der Decoder kann einige Fehler haben, die das verhindern.

Wenn das Bild später aus der zwischengespeicherten Datei abgerufen wird, wird BitmapFactory.decodeFile verwendet, das sich nicht um gestreamte Daten kümmern muss und kann zufällig auf die Bilddatei zugreifen, um das JPEG zu dekodieren. Wenn Sie während des Ladens des Bildes keine zeilenweise Anzeigeaktualisierungen benötigen, würde ich vorschlagen, diesen Codepfad zu löschen und immer das gesamte Bild vor dem Decodieren herunterzuladen.

+0

Ich hatte ähnliche Probleme mit on-the-fly-decodings, so gut. Speichern sie zuerst als temporäre Dateien löste die Probleme. – stpn108