2016-04-05 11 views
0

私は現在、リストビューを持つアプリケーションを開発しています。このリストビューには、XMLファイルからオンラインで取得されたテキストとイメージが挿入されます。ただし、スクロールするたびに、現在画面に表示されていないものはリロードし、ビットマップのサイズを再計算してリストビューに表示します。これは、スクロールが流動的で厄介なことにつながります。どのようにして、リストビューに画像を取り込み、そこにとどまるために1回読み込むためにアクティビティを取得できますか?永久に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

リストビューやスクロールビューを正確に混同しているので、リストビューをスクロールビュー内に置くことは恐ろしい考えです。 –

+0

私はただリストビューだと嘘をついた – MattyK14

答えて

0

この種のものにはキャッシュを使用する必要があります。

Universal Image loaderを参照すると、画像を効率的に読み込むことができます。

あなたは各getViewメソッドでそれをインスタンス化していけない、活動にごimageLoaderのインスタンスを1つだけ持っている必要があります。

は、あなたのonCreate代わりのgetViewメソッドでその行を実行します。

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

ImageLoaderで元の質問を編集しました。 – MattyK14

+0

ImageLoaderは本当に気にしません。すべてのことは、アダプタでgetViewをどのように実装したかによって異なります。 –

+0

アダプターがあります。 – MattyK14

0

Array Listの変数にオンラインデータを保存するようにしてください。次に、notifydatasetChangeを使用してリストビューにロードします。

関連する問題