2012-04-25 5 views
5

Prima di tutto, ho già fatto alcune cose da mostrare un'immagine in GridView rendere liscia quando si scorreIl modo migliore per visualizzare l'immagine in vista griglia scorre liscia

1. caricare l'immagine da internet su thread in background

AsyncTask acyncTask ; 
HandlerThread handlerThread ; 

URL imageUrl = new URL(link);<br> 
      HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection(); 
      conn.setConnectTimeout(30000); 
      conn.setReadTimeout(30000); 
      conn.setInstanceFollowRedirects(true); 
      InputStream is=conn.getInputStream(); 
      final Bitmap bitmap = BitmapFactory.decodeStream(is); 

2. make bitmap alle dimensioni del campione per risparmiare memoria

final BitmapFactory.Options option = new BitmapFactory.Options(); 
    option.inJustDecodeBounds = true; 
    BitmapFactory.decodeFile(mFile.getPath(), 
      option); 
    option.inSampleSize = calculateInSampleSize(option , mSize , mSize); 
    option.inJustDecodeBounds = false; 
    option.inPurgeable = true ; 
    option.inDither = false ; 
    option.inScaled = false ; 
    option.inPreferredConfig = Bitmap.Config.ARGB_8888; 

3. fare una cache per salva decodificato bitmap

LruCache lruCache = new LruCache<String , Bitmap>(); 

in baseadapter getView(); mi lruCache.get(key) di prendere l'immagine bitmap decodificata

4. carico pigro quando bitmap decodificata attraverso gestore

Handler handler = new Handler(); 
     handler.post(new Runnable(){ 
      public void run(){ 
       imageView.setimageBitmap(bitmap); 
      } 
     }); 

Ora sto affrontando un grosso problema, è ancora in ritardo quando sto scorrendo ho google su qualcosa può fare lo scrolling meglio, non so davvero qualcosa può migliorare o il problema è venuto fuori da dove ho controllo per ogni getView() mi spendo solo su 2 ~ 6ms e lo farò chiama il mio codice a async caricando il thread di lavoro modulo immagine, quindi davvero non so perché alcune applicazioni possono caricare molto liscio? il mio caso è quando si scorre lo schermo non sembra molto fluido è qualche suggerimento può applicare?

modificato: mentre faccio scorrere, la bitmap trovato nella cache e la visualizzazione sullo schermo, se ho veloce scorrimento, apparirà come nessun scorrimento abbastanza per mostrare l'immagine, farà il mio scorrimento non così liscio, anche io avere la cache lungo il bitmap nella cache

qui è il codice dell'adattatore:

if (convertView == null) { 
     convertView = layoutInflater.inflate(
       R.layout.row_display_image_grid, null); 
     viewHolder = new DisplayImageGridViewHolder(); 
     viewHolder.background = (RelativeLayout) convertView 
       .findViewById(R.id.background); 
     viewHolder.image = (ImageView) convertView.findViewById(R.id.image); 
     viewHolder.text = (TextView) convertView.findViewById(R.id.text); 
     viewHolder.position = position; 
     viewHolder.text.setEllipsize(TruncateAt.END); 
     viewHolder.text.setTypeface(typeFace); 
     viewHolder.image.setOnClickListener(this); 
     viewHolder.image.setOnLongClickListener(this); 
     convertView.setTag(viewHolder); 
    } else { 
     viewHolder = (DisplayImageGridViewHolder) convertView.getTag(); 
    } 

viewHolder.position = position; 
imageLoader.loadImage(imageLinkList.get(position), viewHolder.image); 
return convertView; 
+0

Puoi pubblicare il tuo codice adattatore, in particolare il metodo getView().Questo è molto probabilmente da dove verrà il ritardo di scorrimento. –

+0

hanno aggiunto, ho appena chiamato un metodo per avviare l'attività di caricamento su un thread di lavoro, ho controllo prima e dopo questo metodo getview, spendo solo pochi millesimi secondi, pensi che setimagebitmap è qualcosa di problema quando si scorre gridview – rex

+0

Il tuo codice è ancora un po 'poco chiaro. Puoi pubblicare la tua intera classe ImageLoader. Sto usando un codice molto simile, probabilmente basato sullo stesso esempio e funziona senza alcun ritardo. –

risposta

4

di seguito è riportato un esempio del LazyLoader che uso. Nota Sto usando SoftReferences per bitmap, questo è ora meglio servito usando LruCache.

Questo caricherà un'immagine in modo asincrono dal web/sdcard/memoria e creerà una dissolvenza in effetto da un'immagine segnaposto.

public class ImageLoader { 

private static MemoryCacheNew memoryCache=new MemoryCacheNew(); 
private static FileCache fileCache; 

private static BitmapFactory.Options bitmapOptions; 

private static int mInSampleSize; 



public ImageLoader(Context context, int inSampleSize){ 


    fileCache=new FileCache(context);   

    context = null; 

    bitmapOptions = new BitmapFactory.Options(); 
    bitmapOptions.inSampleSize = mInSampleSize = inSampleSize; 
    bitmapOptions.inPreferredConfig = Config.RGB_565; 
    bitmapOptions.inInputShareable = true; 
    bitmapOptions.inDither = false; 

} 

final static int PLACEHOLDER_IMAGE = R.drawable.store_placeholder; 

public void DisplayImage(String url, ImageView imageView, boolean checkTags){ 

    try{ 

    new AsyncPhotoTask(imageView, url, checkTags).execute(); 

    }catch(Exception e){ 
     e.printStackTrace(); 
    } 

} 

public void DisplayImage(String url, ImageView imageView) 
{ 
     DisplayImage(url, imageView, true); 

} 


private static Bitmap getBitmap(String url) 
{ 
    File f=fileCache.getFile(url); 


    if(f!= null){ 
    //from SD cache 
    Bitmap b = decodeFile(f); 
    if(b!=null) 
     return b; 
    } 

    //from web 
    try { 
     Bitmap bitmap=null; 

     URL imageUrl; 

      imageUrl = new URL(url); 


     HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection(); 
     conn.setConnectTimeout(30000); 
     conn.setReadTimeout(30000); 
     InputStream is=conn.getInputStream(); 
     OutputStream os = new FileOutputStream(f); 
     Utils.CopyStream(is, os); 
     is.close(); 
     os.close(); 
     bitmap = decodeFile(f); 
     return bitmap; 
    } catch (Exception ex){ 
     ex.printStackTrace(); 
     return null; 
    } 
} 

//decodes image and scales it to reduce memory consumption 
private static Bitmap decodeFile(File f){ 
    try { 
     return BitmapFactory.decodeStream(new FileInputStream(f), null, bitmapOptions); 

    } catch (FileNotFoundException e) { 

    } catch (OutOfMemoryError err){ 
     System.gc(); 
    } 

    return null; 
} 


private static class AsyncPhotoLoad extends AsyncTask<Void, Void, TransitionDrawable>{ 

    private Bitmap bmp; 
    private ImageView imageView; 
    private String url; 
    private boolean checkTags; 

    public AsyncPhotoLoad(ImageView imageView, String url, boolean checkTags 
      ){ 
     this.imageView = imageView; 
     this.url = url; 
     this.checkTags = checkTags; 
    } 

    @Override 
    protected TransitionDrawable doInBackground(Void... arg0) { 

     //check that this is the correct imageview 



     TransitionDrawable transition = null; 

     try{ 
      if(checkTags){ 
      String tag = (String)imageView.getTag();  
      if(!tag.equals(url)) 
       return null; 
      } 

     bmp = getBitmap(url); 

     if(bmp != null){ 
      memoryCache.put(url, bmp, mInSampleSize);  

      Drawable oldDrawable = imageView.getDrawable(); 

      if(!(oldDrawable instanceof TransitionDrawable)){ 

       Drawable layers[] = new Drawable[2];      
       layers[0] = imageView.getDrawable(); 
       layers[1] = new BitmapDrawable(bmp); 

       transition = new TransitionDrawable(layers); 

      } 



     } 

     }catch(Exception e){ 
      e.printStackTrace(); 
     } 

     return transition; 
    } 

    @Override 
    protected void onPostExecute(TransitionDrawable result) { 
     if(result != null){ 
      try{    
       if(checkTags){      
         String tag = (String)imageView.getTag();  
         if(!tag.equals(url)){ 
          return; 
         } 
       } 

        imageView.setImageDrawable(result); 
        result.startTransition(300); 



      } catch(Exception e){ 
       e.printStackTrace(); 
      } 
     } else { 
      if(checkTags){ 
      try{ 
       String tag = (String)imageView.getTag();  
       if(!tag.equals(url)) 
        return; 

      }catch(Exception e){ 
       e.printStackTrace(); 
      } 
      } 


     } 
    } 

} 



private static class AsyncPhotoTask extends AsyncTask<Void, Void, Bitmap>{ 

    private ImageView imageView; 
    private String url; 
    private boolean checkTags; 


    public AsyncPhotoTask(ImageView imageView, String url, boolean checkTags){ 

     this.imageView = imageView; 
     this.url = url; 
     this.checkTags = checkTags; 
    } 


    @Override 
    protected Bitmap doInBackground(Void... params) { 
     try{ 
     if(checkTags) 
      imageView.setTag(url); 

     }catch(Exception e){ 
      e.printStackTrace(); 
     } 

     return memoryCache.get(url, mInSampleSize); 
    } 


    @Override 
    protected void onPostExecute(Bitmap result) { 
     try{ 
     if(result!=null && !result.isRecycled()){ 


      imageView.setImageBitmap(result); 
     } 
     else 
     { 

      imageView.setImageResource(PLACEHOLDER_IMAGE);    
      new AsyncPhotoLoad(imageView, url, checkTags).execute();  

     }  

     }catch(Exception e){ 
      e.printStackTrace(); 
     } 
    } 



} 





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

public static void clearMemory(){ 
    memoryCache.clear(); 
} 

public static class MemoryCacheNew { 
    private HashMap<String, CachedBitmap> cache=new HashMap<String, CachedBitmap>(); 

    public Bitmap get(String id, int sampleSize){ 
     if(!cache.containsKey(id)) 
      return null; 

     if(cache.get(id) == null) 
      return null; 

     if(cache.get(id).sampleSize != sampleSize) 
      return null; 

     SoftReference<Bitmap> ref = cache.get(id).softBitmap; 
     return ref.get(); 
    } 

    public void put(String id, Bitmap bitmap, int sampleSize){ 
     cache.put(id, new CachedBitmap(bitmap, sampleSize)); 
    } 

    public void clear() { 
     cache.clear(); 
    } 



    private static class CachedBitmap { 
     public SoftReference<Bitmap> softBitmap; 
     public int sampleSize; 

     public CachedBitmap(Bitmap bitmap, int sampleSize){ 
      this.softBitmap = new SoftReference<Bitmap>(bitmap); 
      this.sampleSize = sampleSize; 
     } 
    } 
} 


} 


public class FileCache { 

private File cacheDir; 

public FileCache(Context context){ 
    //Find the dir to save cached images 
    if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) 
     cacheDir=new File(context.getExternalCacheDir(),Consts.STORE_CACHE); 
    else 
     cacheDir=context.getCacheDir(); 
    if(!cacheDir.exists()) 
     cacheDir.mkdirs(); 
} 

public File getFile(String url){ 
    //I identify images by hashcode. Not a perfect solution, good for the demo. 
    String filename=String.valueOf(url.hashCode()); 
    File f = new File(cacheDir, filename); 
    return f; 

} 

public void clear(){ 
    File[] files=cacheDir.listFiles(); 
    for(File f:files) 
     f.delete(); 
} 

} 

si chiamano in questo modo:

imageLoader.DisplayImage(url, holder.image); 
+0

sì, si sta utilizzando anche il codice simile, ma non può aiutarmi, mi dispiace – rex

0

cercare di assicurarsi che ogni bitmap di dimensioni ottimali ... dovrebbero essere circa le dimensioni del contenitore. Ridimensionale il più possibile prima di inviarli tramite RemoteViews. Puoi calcolare la dimensione del widget usando onAppWidgetOptionsChanged.

Inoltre, provare a utilizzare setImageViewUri (con un provider di contenuti) invece di setImageViewBitmap per la prestazione ottimale.

Problemi correlati