2016-04-05 2 views
0

Я в настоящее время разрабатываю приложение, где у меня есть список. В этом списке отображается текст и изображения, полученные из XML-файла в Интернете. Он заполняется правильно, однако, всякий раз, когда вы прокручиваете, все, что не было в данный момент на экране, перезагружается и пересчитывает размер растрового изображения, чтобы перейти в список. Это приводит к тому, что прокрутка менее жидкая и раздражающая. Как я могу заставить свою деятельность заполнять список с изображениями и загружать их один раз, чтобы оставаться там?Постоянно заполнять ListView С изображениями?

ImageLoader:

public class ImageLoader { 

MemoryCache memoryCache = new MemoryCache(); 
FileCache fileCache; 
private Map<ImageView, String> imageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>()); 
ExecutorService executorService; 

int size; 
int placeholderpic; 

public ImageLoader(Context context, int size, int placeholderpic) { 
    fileCache = new FileCache(context); 
    executorService = Executors.newFixedThreadPool(5); 
    this.size = size; 
    this.placeholderpic = placeholderpic; 
} 

public void displayImage(String url, ImageView imageView) { 
    imageViews.put(imageView, url); 
    Bitmap bitmap = memoryCache.get(url); 
    if(bitmap != null) 
     imageView.setImageBitmap(bitmap); 
    else { 
     queuePhoto(url, imageView); 
     imageView.setImageResource(placeholderpic); 
    } 
} 

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 = fileCache.getFile(url); 

    //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); 
     return bitmap; 
    } catch (Throwable ex) { 
     ex.printStackTrace(); 
     if(ex instanceof OutOfMemoryError) 
      memoryCache.clear(); 
     return null; 
    } 
} 

//decodes image and scales it to reduce memory consumption 
private Bitmap decodeFile(File f) { 
    try { 
     //decode image size 
     BitmapFactory.Options o = new BitmapFactory.Options(); 
     o.inJustDecodeBounds = true; 
     BitmapFactory.decodeStream(new FileInputStream(f),null,o); 

     //Find the correct scale value. It should be the power of 2. 
     final int REQUIRED_SIZE = size; 
     int width_tmp = o.outWidth, height_tmp=o.outHeight; 
     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; 
     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; 
    } 

    @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); 
     else 
      photoToLoad.imageView.setImageResource(placeholderpic); 
    } 
} 

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

ListView адаптер:

public class LazyNewsAdapter extends BaseAdapter { 

private Activity activity; 
private ArrayList<News> listData; 
private LayoutInflater inflater = null; 

public LazyNewsAdapter(Activity activity, ArrayList<News> listData) { 
    this.activity = activity; 
    this.listData = listData; 
    inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
} 

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

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

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

public View getView(int position, View convertView, ViewGroup parent) { 
    News newsItem = listData.get(position); 

    View view = convertView; 
    if(convertView == null) 
     view = inflater.inflate(R.layout.news_cell, null); 

    TextView newsTitle = (TextView) view.findViewById(R.id.newsTitle); 
    TextView newsDate = (TextView) view.findViewById(R.id.newsDate); 
    ImageView image = (ImageView) view.findViewById(R.id.newsImage); 

    newsTitle.setText(newsItem.getNewsTitle()); 
    newsDate.setText(newsItem.getNewsDate()); 
    String url = newsItem.getNewsImageUrl(); 

    ImageLoader imageLoader = new ImageLoader(activity, 600, R.drawable.placeholder); 
    imageLoader.displayImage(url, image); 

    return view; 
} 
+1

его ужасная идея положить listview внутри scrollview, поскольку это путает систему точно, что вы прокручиваете список или scrollview –

+0

Я солгал, это просто список – MattyK14

ответ

0

Вы должны использовать кеш для такого рода вещей.

См. Universal Image loader, чтобы эффективно загрузить изображения.

Вы должны иметь только один экземпляр вашего imageLoader в деятельности, не правда создать его экземпляр в каждом GetView:

Do эту строку в вашем OnCreate вместо GetView:

ImageLoader imageLoader = new ImageLoader(activity, 600, R.drawable.placeholder); 
+0

Отредактированный исходный вопрос с ImageLoader, который я использую. – MattyK14

+0

Нам не очень-то нравится ваш «ImageLoader». Все зависит от того, как вы реализовали getView на своем адаптере. –

+0

Адаптер есть сейчас. – MattyK14

0

Попробуйте сохранить онлайн данные в список переменных массива. Затем загрузите его в список с помощью notifydatasetChange

0

Используйте оптимизации ListView для установочное изображение в ListAdapter, приведенное в данном руководстве, которое может помочь вам также использовать Glide для настройки изображения, когда они делают шаг вперед по утилизации вашего Bitmap

https://www.youtube.com/watch?v=mKGoKnhN_Ys&index=91&list=PL1q3ROAofjeOUwh7lPBnGbg__DUodwLN7

Смежные вопросы