2012-07-26 7 views
12

서버에서 이미지를 표시하는 응용 프로그램이 있습니다. 이제는 내 이미지를 게으른로드합니다. 처음에는 진행률 표시 줄이 표시됩니다. 이미지로드가 완료되면 속성을 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> 

문제 에 내가 사용하는 레이아웃 파일입니다. 이 이미지처럼

캐시 디렉토리에서로드 된 이미지가 목록을 새로 고칠 때 화면에 표시 될 때 손상없이 올바르게 표시됩니다.

enter image description here

하여 ImageLoader 클래스 내가해서 ProgressDialog 대신하여 ProgressBar를 사용하는 게으른로드 이미지에

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

이미지 로딩을 위해 [Universal Image Loader] (https://github.com/nostra13/Android-Universal-Image-Loader) 라이브러리를 사용해보십시오. 어쩌면이 문제가 없다. – NOSTRA

+0

이미지가로드 될 때 진행 막대를 숨기는 대신 이미지보기를 표시합니다. 로드하기 전에 숨기기 ... – Ronnie

답변

5

시도를 사용합니다. ProgressDialog는 진행률 표시 줄도 사용할 수 있습니다. ProgressDialog는 XML 형식이 아닙니다. 그래서 당신은 show() 또는 dismiss() 메소드를 사용할 수 있습니다. 어쩌면이 문제가 없다. 이 문제는 RelativeLayout에서 비롯된 것 같습니다. ProgressBar Visiblity를 사용하는 경우 RelativeLayout은 여전히 ​​표시가 가능하지만 배경은 없습니다. 또한 RelativeLayout에는 모든 항목이 있습니다. 빈 레이아웃이 당신에게 부패를 준 것 같아요. 해서 ProgressDialog를 사용하는 것이 가장 좋습니다 ..

-1

나는 당신이보기는 여전히 자리를 보유하고 있으며 태 말한 것처럼 RelativeLayout의 몇 가지 문제가 될 수 View.INVISIBLE를 설정할 때 때문에, View.GONE로 가시성을 설정하려고 수 있다고 생각합니다.

건배

3

손상된 영상 방송을 손상-JPEG 아티팩트.

BitmapFactory.decodeStream 방법으로 문제가 발생할 수 있습니다. 모든 JPEG가 즉각적인 디코딩 ('프로그레시브')을 위해 최적화 된 것은 아니므로 제대로 디코딩하기 전에 전체적으로 사용할 수 있어야합니다. 일반적으로 비 프로그레시브 이미지는 위에서 아래로 디코딩 될 수 있지만 모든 파일에 대해 유지되지 않을 수도 있고 디코더가이를 방지하는 결함을 가질 수도 있습니다.

반면에 캐시 된 파일에서 이미지를 나중에 가져 오면 스트림 된 데이터를 신경 쓸 필요가없고 이미지 파일에 임의로 액세스하여 JPEG을 디코딩 할 수 있습니다. 이미지를로드하는 동안 라인 단위의 디스플레이 업데이트가 필요하지 않은 경우,이 코드 경로를 축소하고 모든 이미지를 디코딩하기 전에 항상 다운로드하는 것이 좋습니다.

+0

파리 디코딩에서도 비슷한 문제가있었습니다. 임시 파일로 먼저 저장하면 문제가 해결됩니다. – stpn108

관련 문제