2012-07-26 30 views
12

Tôi có một ứng dụng hiển thị hình ảnh từ máy chủ. bây giờ tôi lười tải hình ảnh của tôi. vì vậy ban đầu tôi sẽ hiển thị thanh tiến trình khi tải xong hình ảnh i xóa thanh tiến trình bằng cách đặt thuộc tính visibility thành View.INVISIBLE và hình ảnh xuất hiện. Đây là file layout tôi sử dụng cho hình ảnhtải hình ảnh chậm với thanh tiến trình thực hiện tham nhũng hình ảnh khi hình ảnh được hiển thị

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

Vấn đề Khi thanh tiến trình biến mất hình ảnh hiển thị trên màn hình nhưng bị hỏng. giống như hình ảnh này

khi tôi làm mới danh sách các hình ảnh được tải từ thư mục bộ nhớ cache và khi chúng được hiển thị trên màn hình chúng hiển thị chính xác mà không bị hỏng.

enter image description here

ImageLoader lớp tôi sử dụng để tải hình ảnh lười biếng

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

Hãy thử sử dụng thư viện [Trình tải ảnh phổ biến] (https://github.com/nostra13/Android-Universal-Image-Loader) để tải hình ảnh. Có lẽ nó không có vấn đề này. – NOSTRA

+0

Thay vì ẩn thanh tiến trình, khi tải hình ảnh, hãy hiển thị số lần xem hình ảnh. Ẩn nó trước khi bắt đầu tải ... – Ronnie

Trả lời

5

Cố gắng sử dụng ProgressDialog thay vì ProgressBar. ProgressDialog cũng có thể sử dụng thanh tiến trình. ProgressDialog không phải là loại XML. để bạn có thể hiển thị phương thức() hoặc loại bỏ(). Có lẽ nó không có vấn đề này. Tôi nghĩ rằng vấn đề này đến từ RelativeLayout. Nếu bạn sử dụng ProgressBar Visiblity, RelativeLayout vẫn có thể hiển thị (nhưng không có nền). RelativeLayout cũng có bất kỳ mục nào. Tôi đoán bố cục trống đã cho bạn tham nhũng. Sử dụng ProgressDialog là tốt nhất ..

-1

Tôi nghĩ bạn có thể cố gắng thiết lập tầm nhìn như View.GONE, bởi vì khi bạn thiết View.INVISIBLE View vẫn giữ nơi này, và giống như Tae nói nó có thể được một số vấn đề với RelativeLayout.

Chúc mừng

3

Hình ảnh bị hỏng hiển thị hình ảnh hư hỏng-JPEG.

Sự cố của bạn có thể phát sinh từ phương pháp BitmapFactory.decodeStream. Không phải tất cả các hình ảnh JPEG đều được tối ưu hóa để giải mã trực tuyến ('tiến bộ') để chúng có thể cần phải có sẵn toàn bộ trước khi được giải mã một cách chính xác. Thông thường, hình ảnh không tiến bộ có thể được giải mã từ trên xuống, nhưng điều đó có thể không giữ cho tất cả các tệp hoặc bộ giải mã có thể có một số lỗi ngăn chặn điều đó.

Mặt khác, nếu hình ảnh sau đó được tìm nạp từ tệp được lưu trữ, BitmapFactory.decodeFile được sử dụng mà không cần quan tâm đến dữ liệu được truyền và có thể truy cập ngẫu nhiên vào tệp hình ảnh để giải mã JPEG. Nếu bạn không cần cập nhật hiển thị từng dòng trong khi tải hình ảnh, tôi khuyên bạn nên bỏ qua đường dẫn mã này và allways tải xuống toàn bộ hình ảnh trước khi giải mã.

+0

Tôi cũng gặp vấn đề tương tự với việc giải mã ruồi. lưu trữ chúng trước tiên như các tập tin tạm thời giải quyết được vấn đề. – stpn108

Các vấn đề liên quan