2012-08-23 3 views
1

나는 목록 항목으로 이미지를 표시하는 사용자 정의 ListView을 만들었습니다. 목록 항목으로 표시되는 이미지는 장치의 내 InternalStorage에 저장됩니다. 항목 수가 많을수록 목록보기 스크롤이 느려지고 스크롤하는 동안 ListView 항목이 느려집니다. 내 코드에 문제가 있거나 내 코드에서 수행 할 작업을 놓쳤습니다. 이 문제를 해결하도록 도와주세요.목록보기 내부 저장소에서 이미지를로드하는 동안 스크롤 속도가 느림

코드 목록보기 항목을 표시

public class ListViewAdapter extends BaseAdapter 
    { 
     private Activity activity; 
     private ArrayList<String> fileNameArray; 
     private LayoutInflater inflater=null; 
     public ImageLoader imageLoader; 

     public ListViewAdapter(Activity a, ArrayList<String> d) 
     { 
      activity = a; 
      fileNameArray = d; 
      inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      imageLoader = new ImageLoader(activity.getApplicationContext()); 
     } 

     public int getCount() 
     { 
      return fileNameArray.size(); 
     } 

     public Object getItem(int position) 
     { 
      return position; 
     } 

     public long getItemId(int position) 
     { 
      return position; 
     } 

     public class ViewHolder 
     { 
      ImageView image; 
     }    

     public View getView(final int position, View convertView, ViewGroup parent) 
     { 
      ViewHolder holder; 

      if(convertView == null) 
      { 
       holder = new ViewHolder(); 
       convertView = inflater.inflate(R.layout.page_list_item, null); 

       holder.image = (ImageView)convertView.findViewById(R.id.image); 

       convertView.setTag(holder); 
      } 
      else 
      { 
       holder = (ViewHolder)convertView.getTag(); 
      }   



      // Load image from internalstoarage and display in image view 

      imageLoader.DisplayImage(m_DirectoryPath.getPath() + "/" + fileNameArray.get(position), holder.image, true); 

      return convertView; 
     } 
} 

당신은 PhotosLoader 스레드 개체에 대해 setPriority를에이 코드 이미지 로더 클래스

public class ImageLoader 
{ 
    MemoryCache memoryCache = new MemoryCache(); 
    private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>()); 
    ExecutorService executorService; 
    Context m_context; 
    public ImageLoader(Context context) 
    { 
     m_context = context; 
     executorService = Executors.newFixedThreadPool(5); 
    } 

    public void DisplayImage(String url, ImageView imageView, boolean useCachedImage) 
    { 
     imageViews.put(imageView, url); 
     Bitmap bitmap = memoryCache.get(url); 

     if(bitmap!=null && useCachedImage) 
     { 
      imageView.setImageBitmap(bitmap); 
     } 
     else 
     { 
      queuePhoto(url, imageView); 
     } 
    } 

    private void queuePhoto(String url, ImageView imageView) 
    { 
     PhotoToLoad p = new PhotoToLoad(url, imageView); 
     executorService.submit(new PhotosLoader(p)); 
    } 

    private Bitmap getBitmap(String url) 
    { 
     File filePath = new File(url); 

     // from internal storage cache 
     Bitmap b = decodeFile(filePath); 
     if (b != null) 
     { 
      return b; 
     } 
     return null; 
    } 

    // decodes image and scales it to reduce memory consumption 
    private Bitmap decodeFile(File filePath) 
    { 
     try 
     { 
      // decode image size 
      int Required_Height = 0; 

      BitmapFactory.Options option = new BitmapFactory.Options();    
      Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(filePath), null, option); 

      WindowManager wm = (WindowManager) m_context.getSystemService(Context.WINDOW_SERVICE); 
      Display display = wm.getDefaultDisplay(); 

      if(display.getWidth() == 480) 
      { 
       Required_Height = 150; 
      } 
      else if(display.getWidth() == 800) 
      { 
       Required_Height = 200; 
      } 

      bitmap = Bitmap.createBitmap(bitmap, 0, 0, option.outWidth, Required_Height); 

      return bitmap; 
     } 
     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; 
     } 

     @Override 
     public void run() 
     { 
      if(imageViewReused(photoToLoad)) 
       return; 

      Bitmap bmp = getBitmap(photoToLoad.url); 
      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; 

      if(bitmap != null) 
       photoToLoad.imageView.setImageBitmap(bitmap); 
     } 
    } 

    public void clearCache() 
    { 
     memoryCache.clear(); 
    } 

} 

답변

1

을 위해. 나는 이와 같은 생성자에서 이것을하고있다.

// Make the background thread low priority. This way it will not affect the UI performance 
mImageRequstController.setPriority(Thread.NORM_PRIORITY - 1); 

우선 순위를 낮게 설정하면 UI에 영향을 미치지 않으며 백그라운드에서 계속 작동합니다.

+0

어떻게 할 수 있습니까? 나를 설명해주세요. 제 코드에서 어떻게 할 수 있습니까? – Rahul

+0

Executors.newFixedThreadPool (5); – Arslan

+0

나는 이것에 대한 어떤 코드도 가지고 있지 않다. 이것은 ExecutorService 클래스가 제공하는 기본 메소드이다. – Rahul

0

속도 상 이유로 목록 항목이 보이지 않을 때까지로드되지 않습니다. 사용자가 목록 항목을보기로 스크롤하면 해당 항목이로드됩니다. 그러나 SD 카드에서 이미지를로드하는 것은 사용자가 지연을 볼 수있을만큼 충분히 시간이 많이 소요됩니다.

코드가 이미지를 UI 스레드에로드하여 업데이트하지 못하도록하고 원활하게 스크롤합니다. 대신 이미지를로드 할 때까지 UI 스레드의 목록 항목에 진행률 회 전자 또는 다른 로딩 표시기 만 표시해야하는 반면 다른 스레드에서 이미지를로드해야합니다. 목록과 마찬가지로 스레드는 목록 항목이 한 번에보기가 아닌 경우에만 시작되어야합니다.

+0

나는 별도의 스레드에서 UI를 로딩하는 많은 예제를 보았지만, 어떻게하면 내 코드에서 구현할 수 있을지 알 수 없었다. 내 코드에서 어떻게 할 수 있는지 알고 싶습니다. – Rahul

+0

@RahulBorah : 아니, 코드를 보여주지 않겠습니다. 내가 한 경우 학습하지 않고 복사 붙여 넣기를 권하고 싶습니다. 네가 그걸 이해하기를 바란다. 그러나, 그것은 상당히 사소한 일입니다. 이미지를로드 진행률 이미지로 설정합니다. 이미지를 비트 맵이나 다른 것으로로드하는 스레드를 시작하십시오. 스레드가 완료되면 이미지를 뷰에 놓는 Handler를 호출합니다. 그게 다야. – AlbeyAmakiir

관련 문제