2012-04-25 22 views
5

En primer lugar, ya he hecho algunas cosas para mostrar la imagen en gridview hacer suave cuandomejor manera de mostrar la imagen en la vista de cuadrícula es el desplazamiento suave

1. Imagen de carga desplazándose desde Internet en subproceso de fondo

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. maquillaje de mapa de bits tamaño de la muestra para ahorrar 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. Haga una memoria caché de mapa de bits decodificado para salvar

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

en baseadapter getView(); voy a lruCache.get(key) tomar el mapa de bits decodificado

4. carga perezosa a través de mapa de bits decodificado manejador

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

Ahora estoy enfrentando un gran problema, todavía me queda un poco cuando estoy desplazándome tengo google sobre algo que puede hacer que se desplace mejor, no sé si realmente algo puede mejorar o si el problema se presenta desde donde tengo control para cada getView() solo me gasta aproximadamente 2 ~ 6ms y lo hará llamar a mi código a async cargando la imagen del hilo de trabajo, así que realmente no sé por qué algunas aplicaciones pueden cargar muy suave? mi caso es cuando se desplaza, la pantalla no se verá muy suave ¿se puede aplicar alguna sugerencia?

editado: cuando estoy desplazándome, el mapa de bits se encuentra en la caché y se muestra en la pantalla, si me desplazo rápidamente, parecerá que no hay desplazamiento suficiente para mostrar la imagen, hará que mi desplazamiento no sea tan uniforme, incluso tienen caché por el mapa de bits en caché

aquí es el código de adaptador:

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

Puede publicar su código de adaptador, específicamente el método getView().Es más probable de donde vendrá el desfase de desplazamiento. –

+0

he agregado, simplemente llamo a un método para iniciar la tarea de carga en un subproceso de trabajo, tengo verificación antes y después de este método de getview, solo gasta mis pocos segundos, ¿piensas que setimagebitmap es un problema al desplazar a gridview – rex

+0

Tu código todavía no está claro. ¿Puedes publicar toda tu clase de ImageLoader? Estoy usando un código muy similar, posiblemente basado en el mismo ejemplo y lo tengo trabajando sin retraso. –

Respuesta

4

a continuación se muestra un ejemplo de la LazyLoader utilizo. Tenga en cuenta que estoy utilizando SoftReferences para mapas de bits, ahora esto se sirve mejor usando LruCache.

Esto cargará una imagen de forma asíncrona desde la web/sdcard/memory y creará un fundido de efecto a partir de una imagen de marcador de posición.

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

} 

Se llaman así:

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

sí, también estás usando el código similar, pero no puede ayudarme, lo siento – rex

0

tratar de asegurarse de que cada mapa de bits de tamaño optimizado ... deberían ser del tamaño del contenedor. Escalarlos tanto como puedas antes de enviarlos a través de RemoteViews. Puede calcular el tamaño del widget utilizando onAppWidgetOptionsChanged.

Además, intente usar setImageViewUri (con un proveedor de contenido) en lugar de setImageViewBitmap para obtener el rendimiento óptimo.

Cuestiones relacionadas