Android_异步加载2
接着这篇博客写:http://blog.csdn.net/two_water/article/details/51477206
异步加载1这篇博客在最后暴露出了一个问题,就是只在ListView的最后一个Item的ImageView刷新图片,解决问题的方案也提出来了,需要让url和对应的ImageView进行下配对!
ImageLoader的代码把showImageByThread方法里面的判断是否有缓存图片的代码注释了,改到在Adapter那里进行判断,判断是否有缓存图片,如果有显示缓存的图片,如果没有就先显示默认加载的图片,然后再去加载网络图片,并添加缓存!
- package com.liangdianshui.asynchronouslyload;
 - import android.content.Context;
 - import android.graphics.Bitmap;
 - import android.view.LayoutInflater;
 - import android.view.View;
 - import android.view.ViewGroup;
 - import android.widget.BaseAdapter;
 - import android.widget.ImageView;
 - import android.widget.TextView;
 - import java.util.List;
 - /**
 - * Created by 两点水 on 2016/5/12.
 - */
 - public class MyAdapter extends BaseAdapter {
 - private Context context;
 - private List<DataBean> list;
 - private ViewHolder mHolder;
 - private ImageLoader mImaeLoader;
 - public MyAdapter(Context context, List<DataBean> list) {
 - this.context = context;
 - this.list = list;
 - mImaeLoader = new ImageLoader(); //因为创建了缓存空间,所以放在构造方法,只创建一次
 - }
 - @Override
 - public int getCount() {
 - return list.size();
 - }
 - @Override
 - public Object getItem(int position) {
 - return list.get(position);
 - }
 - @Override
 - public long getItemId(int position) {
 - return position;
 - }
 - @Override
 - public View getView(int position, View convertView, ViewGroup parent) {
 - if (convertView == null) {
 - convertView = LayoutInflater.from(context).inflate(R.layout.item_layout, null);
 - mHolder = new ViewHolder();
 - mHolder.tvTitle = (TextView) convertView.findViewById(R.id.tv_title);
 - mHolder.tvContent = (TextView) convertView.findViewById(R.id.tv_content);
 - mHolder.ivIcon = (ImageView) convertView.findViewById(R.id.iv_icon);
 - convertView.setTag(mHolder);
 - } else {
 - mHolder = (ViewHolder) convertView.getTag();
 - }
 - // mHolder.ivIcon.setImageResource(R.mipmap.ic_launcher);//默认加载的图片
 - String url = list.get(position).getDataIconUrl();
 - mHolder.ivIcon.setTag(url);//为防止listview显示的图片错乱,重复,闪烁
 - // new ImageLoader().showImageByThread(mHolder.ivIcon, url);
 - Bitmap bitmapFromCache = mImaeLoader.getBitmapFromCache(url);
 - if (bitmapFromCache != null) {
 - mHolder.ivIcon.setImageBitmap(bitmapFromCache);
 - }else{
 - mHolder.ivIcon.setImageResource(R.mipmap.ic_launcher);
 - mImaeLoader.showImageByThread(mHolder.ivIcon, url);
 - }
 - mHolder.tvTitle.setText(list.get(position).getDataTitle());
 - mHolder.tvContent.setText(list.get(position).getDataContent());
 - return convertView;
 - }
 - class ViewHolder {
 - private TextView tvTitle;
 - private TextView tvContent;
 - private ImageView ivIcon;
 - }
 - }
 
ImageLoader的代码:
- package com.liangdianshui.asynchronouslyload;
 - import android.graphics.Bitmap;
 - import android.graphics.BitmapFactory;
 - import android.os.Handler;
 - import android.os.Message;
 - import android.util.LruCache;
 - import android.widget.ImageView;
 - import java.io.BufferedInputStream;
 - import java.io.IOException;
 - import java.io.InputStream;
 - import java.net.HttpURLConnection;
 - import java.net.MalformedURLException;
 - import java.net.URL;
 - /**
 - * Created by 两点水 on 2016/5/22.
 - */
 - public class ImageLoader {
 - private ImageView mImageView;
 - private String mUrl;
 - private final int URL_BITMAP = 0;
 - private LruCache<String, Bitmap> mCache; //使用Lru缓存(使用的Lru算法:近期最少使用算法)
 - /**
 - * 使用缓存肯定要先声明缓存空间,因此在构造方法中声明缓存空间
 - */
 - public ImageLoader() {
 - //获取程序最大使用的内存
 - int maxMemory = (int) Runtime.getRuntime().maxMemory();
 - int cacheSize = maxMemory / 4; //缓存大小为最大缓存的四分之一
 - //创建缓存,把缓存大小传进去
 - mCache = new LruCache<String, Bitmap>(cacheSize) {
 - @Override
 - protected int sizeOf(String key, Bitmap value) {
 - //每次存入缓存的时候都会调用这个方法,因此我们把图片的大小放进去
 - return value.getByteCount();
 - }
 - };
 - }
 - /**
 - * 把图片加入到缓存
 - *
 - * @param url
 - * @param bitmap
 - */
 - public void addBitmapToCache(String url, Bitmap bitmap) {
 - //LruCache好比是一个map,采用键值对的形式去保存图片
 - if (getBitmapFromCache(url) == null) {
 - //如果缓存中没有这个Bitmap,就把bitmap放进缓存
 - mCache.put(url, bitmap);
 - }
 - }
 - /**
 - * 从缓存中获取图片
 - *
 - * @param url
 - */
 - public Bitmap getBitmapFromCache(String url) {
 - return mCache.get(url); //根据url获取图片
 - }
 - Handler mHandler = new Handler() {
 - @Override
 - public void handleMessage(Message msg) {
 - super.handleMessage(msg);
 - switch (msg.what) {
 - case URL_BITMAP:
 - // if (mImageView.getTag().equals(mUrl)) {
 - // mImageView.setImageBitmap((Bitmap) msg.obj);
 - // }
 - //因为传过来的对象更改了,这里也要跟着更改
 - ImgHolder holder = (ImgHolder) msg.obj;
 - if (holder.imageView.getTag().equals(holder.url)) {
 - holder.imageView.setImageBitmap(holder.bitmap);
 - }
 - break;
 - }
 - }
 - };
 - /**
 - * 多线程加载图片(Thread+Handler)
 - * 根据url获取的itmap显示在ImageView中
 - *
 - * @param imageView
 - * @param url
 - */
 - public void showImageByThread(final ImageView imageView, final String url) {
 - mImageView = imageView;
 - mUrl = url;
 - //从缓存中取出图片
 - // Bitmap bitmap = getBitmapFromCache(url);
 - //判断缓存中是否含有这张图片,没有的话去网络下载图片
 - // if (bitmap == null) {
 - new Thread(new Runnable() {
 - @Override
 - public void run() {
 - Bitmap bitmap = getBitmapFromURL(url);
 - //把下载下来的图片加到缓存中
 - if (bitmap != null) {
 - addBitmapToCache(url, bitmap);
 - }
 - Message message = new Message();
 - // message.obj = bitmap;
 - //为了保证ImageView与这时候传递过来的图像一一对应的关系
 - message.obj = new ImgHolder(imageView, bitmap, url);
 - message.what = URL_BITMAP;
 - mHandler.sendMessage(message);
 - }
 - }).start(); //记得start();
 - // } else {
 - // Message message = new Message();
 - // message.obj = bitmap;
 - //为了保证ImageView与这时候传递过来的图像一一对应的关系
 - // message.obj = new ImgHolder(imageView, bitmap, url);
 - // message.what = URL_BITMAP;
 - // mHandler.sendMessage(message);
 - // }
 - }
 - /**
 - * 根据rul获取bitmap
 - *
 - * @param url
 - * @return
 - */
 - private Bitmap getBitmapFromURL(String url) {
 - InputStream inputStream = null;
 - try {
 - URL urlBitmap = new URL(url);
 - HttpURLConnection urlConnection = (HttpURLConnection) urlBitmap.openConnection();
 - inputStream = new BufferedInputStream(urlConnection.getInputStream());
 - Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
 - Thread.sleep(1000); //模拟网速慢的情况,为了更好的显示ImageView刷新多次的情况
 - urlConnection.disconnect(); //关闭http连接
 - return bitmap;
 - } catch (MalformedURLException e) {
 - e.printStackTrace();
 - } catch (IOException e) {
 - e.printStackTrace();
 - } catch (InterruptedException e) {
 - e.printStackTrace();
 - } finally {
 - try {
 - inputStream.close(); //关闭流
 - } catch (IOException e) {
 - e.printStackTrace();
 - }
 - }
 - return null;
 - }
 - /**
 - * 新建一个类,记录ImageView,bitmap和url
 - */
 - private class ImgHolder {
 - public Bitmap bitmap;
 - public ImageView imageView;
 - public String url;
 - public ImgHolder(ImageView iv, Bitmap bm, String url) {
 - this.imageView = iv;
 - this.bitmap = bm;
 - this.url = url;
 - }
 - }
 - }
 
效果图:
使用AsyncTask实现上面的效果,其实AsyncTask也是根据多线程来实现的,因此基本的实现方式是一样的,直接贴代码:
- package com.liangdianshui.asynchronouslyload;
 - import android.graphics.Bitmap;
 - import android.graphics.BitmapFactory;
 - import android.os.AsyncTask;
 - import android.os.Handler;
 - import android.os.Message;
 - import android.util.LruCache;
 - import android.widget.ImageView;
 - import java.io.BufferedInputStream;
 - import java.io.IOException;
 - import java.io.InputStream;
 - import java.net.HttpURLConnection;
 - import java.net.MalformedURLException;
 - import java.net.URL;
 - /**
 - * Created by 两点水 on 2016/5/22.
 - */
 - public class ImageLoader {
 - private ImageView mImageView;
 - private String mUrl;
 - private final int URL_BITMAP = 0;
 - private LruCache<String, Bitmap> mCache; //使用Lru缓存(使用的Lru算法:近期最少使用算法)
 - /**
 - * 使用缓存肯定要先声明缓存空间,因此在构造方法中声明缓存空间
 - */
 - public ImageLoader() {
 - //获取程序最大使用的内存
 - int maxMemory = (int) Runtime.getRuntime().maxMemory();
 - int cacheSize = maxMemory / 4; //缓存大小为最大缓存的四分之一
 - //创建缓存,把缓存大小传进去
 - mCache = new LruCache<String, Bitmap>(cacheSize) {
 - @Override
 - protected int sizeOf(String key, Bitmap value) {
 - //每次存入缓存的时候都会调用这个方法,因此我们把图片的大小放进去
 - return value.getByteCount();
 - }
 - };
 - }
 - /**
 - * 把图片加入到缓存
 - *
 - * @param url
 - * @param bitmap
 - */
 - public void addBitmapToCache(String url, Bitmap bitmap) {
 - //LruCache好比是一个map,采用键值对的形式去保存图片
 - if (getBitmapFromCache(url) == null) {
 - //如果缓存中没有这个Bitmap,就把bitmap放进缓存
 - mCache.put(url, bitmap);
 - }
 - }
 - /**
 - * 从缓存中获取图片
 - *
 - * @param url
 - */
 - public Bitmap getBitmapFromCache(String url) {
 - return mCache.get(url); //根据url获取图片
 - }
 - Handler mHandler = new Handler() {
 - @Override
 - public void handleMessage(Message msg) {
 - super.handleMessage(msg);
 - switch (msg.what) {
 - case URL_BITMAP:
 - // if (mImageView.getTag().equals(mUrl)) {
 - // mImageView.setImageBitmap((Bitmap) msg.obj);
 - // }
 - //因为传过来的对象更改了,这里也要跟着更改
 - ImgHolder holder = (ImgHolder) msg.obj;
 - if (holder.imageView.getTag().equals(holder.url)) {
 - holder.imageView.setImageBitmap(holder.bitmap);
 - }
 - break;
 - }
 - }
 - };
 - /**
 - * 多线程加载图片(Thread+Handler)
 - * 根据url获取的itmap显示在ImageView中
 - *
 - * @param imageView
 - * @param url
 - */
 - public void showImageByThread(final ImageView imageView, final String url) {
 - mImageView = imageView;
 - mUrl = url;
 - //从缓存中取出图片
 - // Bitmap bitmap = getBitmapFromCache(url);
 - //判断缓存中是否含有这张图片,没有的话去网络下载图片
 - // if (bitmap == null) {
 - new Thread(new Runnable() {
 - @Override
 - public void run() {
 - Bitmap bitmap = getBitmapFromURL(url);
 - //把下载下来的图片加到缓存中
 - if (bitmap != null) {
 - addBitmapToCache(url, bitmap);
 - }
 - Message message = new Message();
 - // message.obj = bitmap;
 - //为了保证ImageView与这时候传递过来的图像一一对应的关系
 - message.obj = new ImgHolder(imageView, bitmap, url);
 - message.what = URL_BITMAP;
 - mHandler.sendMessage(message);
 - }
 - }).start(); //记得start();
 - // } else {
 - // Message message = new Message();
 - // message.obj = bitmap;
 - //为了保证ImageView与这时候传递过来的图像一一对应的关系
 - // message.obj = new ImgHolder(imageView, bitmap, url);
 - // message.what = URL_BITMAP;
 - // mHandler.sendMessage(message);
 - // }
 - }
 - /**
 - * 根据rul获取bitmap
 - *
 - * @param url
 - * @return
 - */
 - private Bitmap getBitmapFromURL(String url) {
 - InputStream inputStream = null;
 - try {
 - URL urlBitmap = new URL(url);
 - HttpURLConnection urlConnection = (HttpURLConnection) urlBitmap.openConnection();
 - inputStream = new BufferedInputStream(urlConnection.getInputStream());
 - Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
 - // Thread.sleep(1000); //模拟网速慢的情况,为了更好的显示ImageView刷新多次的情况
 - urlConnection.disconnect(); //关闭http连接
 - return bitmap;
 - } catch (MalformedURLException e) {
 - e.printStackTrace();
 - } catch (IOException e) {
 - e.printStackTrace();
 - } finally {
 - try {
 - inputStream.close(); //关闭流
 - } catch (IOException e) {
 - e.printStackTrace();
 - }
 - }
 - return null;
 - }
 - /**
 - * 新建一个类,记录ImageView,bitmap和url
 - */
 - private class ImgHolder {
 - public Bitmap bitmap;
 - public ImageView imageView;
 - public String url;
 - public ImgHolder(ImageView iv, Bitmap bm, String url) {
 - this.imageView = iv;
 - this.bitmap = bm;
 - this.url = url;
 - }
 - }
 - /**
 - * 通过AsyncTask异步加载图片显示到ImageView
 - *
 - * @param imageView
 - * @param url
 - */
 - public void showImageByAsyncTask(ImageView imageView, String url) {
 - Bitmap bitmap = getBitmapFromCache(url);
 - if (bitmap == null) { //判断缓存是否有对应的图片
 - new MyAsyncTask(imageView, url).execute(url);
 - } else {
 - imageView.setImageBitmap(bitmap);
 - }
 - }
 - /**
 - * 创建MyAsyncTask内部类
 - * 通过AsyncTask异步加载图片
 - */
 - private class MyAsyncTask extends AsyncTask<String, Void, Bitmap> {
 - private ImageView mImageView;
 - private String mUrl;
 - /**
 - * 创建构造方法初始化ImagaeView
 - */
 - public MyAsyncTask(ImageView imageView, String url) {
 - mImageView = imageView;
 - mUrl = url;
 - }
 - @Override
 - protected void onPreExecute() {
 - super.onPreExecute();
 - }
 - @Override
 - protected Bitmap doInBackground(String... params) {
 - String url = params[0];
 - Bitmap bitmap = getBitmapFromURL(url);
 - if (bitmap != null) {
 - addBitmapToCache(url, bitmap); //增叫图片到缓存
 - }
 - return bitmap;
 - }
 - @Override
 - protected void onPostExecute(Bitmap bitmap) {
 - super.onPostExecute(bitmap);
 - if (mImageView.getTag().equals(mUrl)) {
 - mImageView.setImageBitmap(bitmap);
 - }
 - }
 - }
 - }
 
Adapter的代码:
- package com.liangdianshui.asynchronouslyload;
 - import android.content.Context;
 - import android.graphics.Bitmap;
 - import android.view.LayoutInflater;
 - import android.view.View;
 - import android.view.ViewGroup;
 - import android.widget.BaseAdapter;
 - import android.widget.ImageView;
 - import android.widget.TextView;
 - import java.util.List;
 - /**
 - * Created by 两点水 on 2016/5/12.
 - */
 - public class MyAdapter extends BaseAdapter {
 - private Context context;
 - private List<DataBean> list;
 - private ViewHolder mHolder;
 - private ImageLoader mImaeLoader;
 - public MyAdapter(Context context, List<DataBean> list) {
 - this.context = context;
 - this.list = list;
 - mImaeLoader = new ImageLoader(); //因为创建了缓存空间,所以放在构造方法,只创建一次
 - }
 - @Override
 - public int getCount() {
 - return list.size();
 - }
 - @Override
 - public Object getItem(int position) {
 - return list.get(position);
 - }
 - @Override
 - public long getItemId(int position) {
 - return position;
 - }
 - @Override
 - public View getView(int position, View convertView, ViewGroup parent) {
 - if (convertView == null) {
 - convertView = LayoutInflater.from(context).inflate(R.layout.item_layout, null);
 - mHolder = new ViewHolder();
 - mHolder.tvTitle = (TextView) convertView.findViewById(R.id.tv_title);
 - mHolder.tvContent = (TextView) convertView.findViewById(R.id.tv_content);
 - mHolder.ivIcon = (ImageView) convertView.findViewById(R.id.iv_icon);
 - convertView.setTag(mHolder);
 - } else {
 - mHolder = (ViewHolder) convertView.getTag();
 - }
 - // mHolder.ivIcon.setImageResource(R.mipmap.ic_launcher);//默认加载的图片
 - String url = list.get(position).getDataIconUrl();
 - mHolder.ivIcon.setTag(url);//为防止listview显示的图片错乱,重复,闪烁
 - // new ImageLoader().showImageByThread(mHolder.ivIcon, url);
 - /**
 - * 注释多线程异步加载图片的代码
 - */
 - // Bitmap bitmapFromCache = mImaeLoader.getBitmapFromCache(url);
 - // if (bitmapFromCache != null) {
 - // mHolder.ivIcon.setImageBitmap(bitmapFromCache);
 - // } else {
 - // mHolder.ivIcon.setImageResource(R.mipmap.ic_launcher);
 - // mImaeLoader.showImageByThread(mHolder.ivIcon, url);
 - // }
 - /**
 - *使用AsyncTask的方式实现多线程
 - */
 - mHolder.ivIcon.setImageResource(R.mipmap.ic_launcher);//默认加载的图片
 - mImaeLoader.showImageByAsyncTask(mHolder.ivIcon, url);
 - mHolder.tvTitle.setText(list.get(position).getDataTitle());
 - mHolder.tvContent.setText(list.get(position).getDataContent());
 - return convertView;
 - }
 - class ViewHolder {
 - private TextView tvTitle;
 - private TextView tvContent;
 - private ImageView ivIcon;
 - }
 - }
 
       效果图跟上面多线程实现的效果图是一样的!
ListView滚动时的高效优化:
           为什么要进行ListView滚动时的优化呢?当Item的界面很复杂的时候,我们的做法是一边滚动时还在加载图片的,加载完成后在主线程中更新ImageView,如果刚好在滚动的时候,更新ImageVIew,因为都是在主线程工作,这时候可能会有卡顿的现象!
       为了解决这种卡顿的现象,我们可以在用户滚动ListView的时候不更新ImageVeiw,只有当用户停止滚动的时候才更新,这样就不卡顿了!
       因此Adapter首先要监听滑动事件,在第一次加载的时候进行加载更新可见项item的视图,之后都是在ListView滑动停止的时候才更新加载图片,其余情况不加载图片!
- package com.liangdianshui.asynchronouslyload;
 - import android.content.Context;
 - import android.view.LayoutInflater;
 - import android.view.View;
 - import android.view.ViewGroup;
 - import android.widget.AbsListView;
 - import android.widget.BaseAdapter;
 - import android.widget.ImageView;
 - import android.widget.ListView;
 - import android.widget.TextView;
 - import java.util.List;
 - /**
 - * Created by 两点水 on 2016/5/12.
 - */
 - public class MyAdapter extends BaseAdapter implements AbsListView.OnScrollListener {
 - private Context context;
 - private List<DataBean> list;
 - private ViewHolder mHolder;
 - private ImageLoader mImaeLoader;
 - private int mStart, mEnd;//当前可见项的起始位置
 - public static String URLS[];//用于保存所有的图片URL地址
 - private boolean mFirstIn;//用于判断是否首次启动预加载
 - public MyAdapter(Context context, List<DataBean> list, ListView listView) {
 - this.context = context;
 - this.list = list;
 - mFirstIn = true;
 - mImaeLoader = new ImageLoader(listView); //因为创建了缓存空间,所以放在构造方法,只创建一次
 - //保存所有的图片URL地址
 - URLS = new String[list.size()];
 - for (int i = 0; i < URLS.length; i++) {
 - URLS[i] = list.get(i).getDataIconUrl();
 - }
 - //实现listview滑动监听接口
 - listView.setOnScrollListener(this);
 - }
 - @Override
 - public int getCount() {
 - return list.size();
 - }
 - @Override
 - public Object getItem(int position) {
 - return list.get(position);
 - }
 - @Override
 - public long getItemId(int position) {
 - return position;
 - }
 - @Override
 - public View getView(int position, View convertView, ViewGroup parent) {
 - if (convertView == null) {
 - convertView = LayoutInflater.from(context).inflate(R.layout.item_layout, null);
 - mHolder = new ViewHolder();
 - mHolder.tvTitle = (TextView) convertView.findViewById(R.id.tv_title);
 - mHolder.tvContent = (TextView) convertView.findViewById(R.id.tv_content);
 - mHolder.ivIcon = (ImageView) convertView.findViewById(R.id.iv_icon);
 - convertView.setTag(mHolder);
 - } else {
 - mHolder = (ViewHolder) convertView.getTag();
 - }
 - // mHolder.ivIcon.setImageResource(R.mipmap.ic_launcher);//默认加载的图片
 - String url = list.get(position).getDataIconUrl();
 - mHolder.ivIcon.setTag(url);//为防止listview显示的图片错乱,重复,闪烁
 - // new ImageLoader().showImageByThread(mHolder.ivIcon, url);
 - /**
 - * 多线程异步加载图片
 - */
 - // Bitmap bitmapFromCache = mImaeLoader.getBitmapFromCache(url);
 - // if (bitmapFromCache != null) {
 - // mHolder.ivIcon.setImageBitmap(bitmapFromCache);
 - // } else {
 - // mHolder.ivIcon.setImageResource(R.mipmap.ic_launcher);
 - // mImaeLoader.showImageByThread(mHolder.ivIcon, url);
 - // }
 - /**
 - *使用AsyncTask的方式实现多线程
 - */
 - // mHolder.ivIcon.setImageResource(R.mipmap.ic_launcher);//默认加载的图片
 - mImaeLoader.showImageByAsyncTask(mHolder.ivIcon, url);
 - mHolder.tvTitle.setText(list.get(position).getDataTitle());
 - mHolder.tvContent.setText(list.get(position).getDataContent());
 - return convertView;
 - }
 - @Override
 - public void onScrollStateChanged(AbsListView view, int scrollState) {
 - //滚动状态为停止时,加载当前可见的数据项
 - if (scrollState == SCROLL_STATE_IDLE) {
 - mImaeLoader.loadPartImageView(mStart, mEnd);
 - } else {//滑动没有停止时,停止任务
 - mImaeLoader.CancelAllTask();
 - }
 - }
 - @Override
 - public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
 - mStart = firstVisibleItem;
 - mEnd = firstVisibleItem + visibleItemCount;
 - //首次启动预加载
 - if (mFirstIn && visibleItemCount > 0) {
 - mImaeLoader.loadPartImageView(mStart, mEnd);
 - mFirstIn = false;
 - }
 - }
 - class ViewHolder {
 - private TextView tvTitle;
 - private TextView tvContent;
 - private ImageView ivIcon;
 - }
 - }
 
ImageLoader中写一个加载可见项视图Item的方法,然后修改下异步加载图片的方法:
- package com.liangdianshui.asynchronouslyload;
 - import android.graphics.Bitmap;
 - import android.graphics.BitmapFactory;
 - import android.os.AsyncTask;
 - import android.os.Handler;
 - import android.os.Message;
 - import android.util.LruCache;
 - import android.widget.ImageView;
 - import android.widget.ListView;
 - import java.io.BufferedInputStream;
 - import java.io.IOException;
 - import java.io.InputStream;
 - import java.net.HttpURLConnection;
 - import java.net.MalformedURLException;
 - import java.net.URL;
 - import java.util.HashSet;
 - import java.util.Set;
 - /**
 - * Created by 两点水 on 2016/5/22.
 - */
 - public class ImageLoader {
 - private ImageView mImageView;
 - private String mUrl;
 - private final int URL_BITMAP = 0;
 - private LruCache<String, Bitmap> mCache; //使用Lru缓存(使用的Lru算法:近期最少使用算法)
 - private ListView mlistView;
 - private Set<MyAsyncTask> mTasks;
 - /**
 - * 使用缓存肯定要先声明缓存空间,因此在构造方法中声明缓存空间
 - */
 - public ImageLoader(ListView listView) {
 - this.mlistView = listView;
 - mTasks = new HashSet<>();
 - //获取程序最大使用的内存
 - int maxMemory = (int) Runtime.getRuntime().maxMemory();
 - int cacheSize = maxMemory / 4; //缓存大小为最大缓存的四分之一
 - //创建缓存,把缓存大小传进去
 - mCache = new LruCache<String, Bitmap>(cacheSize) {
 - @Override
 - protected int sizeOf(String key, Bitmap value) {
 - //每次存入缓存的时候都会调用这个方法,因此我们把图片的大小放进去
 - return value.getByteCount();
 - }
 - };
 - }
 - /**
 - * 把图片加入到缓存
 - *
 - * @param url
 - * @param bitmap
 - */
 - public void addBitmapToCache(String url, Bitmap bitmap) {
 - //LruCache好比是一个map,采用键值对的形式去保存图片
 - if (getBitmapFromCache(url) == null) {
 - //如果缓存中没有这个Bitmap,就把bitmap放进缓存
 - mCache.put(url, bitmap);
 - }
 - }
 - /**
 - * 从缓存中获取图片
 - *
 - * @param url
 - */
 - public Bitmap getBitmapFromCache(String url) {
 - return mCache.get(url); //根据url获取图片
 - }
 - Handler mHandler = new Handler() {
 - @Override
 - public void handleMessage(Message msg) {
 - super.handleMessage(msg);
 - switch (msg.what) {
 - case URL_BITMAP:
 - // if (mImageView.getTag().equals(mUrl)) {
 - // mImageView.setImageBitmap((Bitmap) msg.obj);
 - // }
 - //因为传过来的对象更改了,这里也要跟着更改
 - ImgHolder holder = (ImgHolder) msg.obj;
 - if (holder.imageView.getTag().equals(holder.url)) {
 - holder.imageView.setImageBitmap(holder.bitmap);
 - }
 - break;
 - }
 - }
 - };
 - /**
 - * 多线程加载图片(Thread+Handler)
 - * 根据url获取的itmap显示在ImageView中
 - *
 - * @param imageView
 - * @param url
 - */
 - public void showImageByThread(final ImageView imageView, final String url) {
 - mImageView = imageView;
 - mUrl = url;
 - //从缓存中取出图片
 - // Bitmap bitmap = getBitmapFromCache(url);
 - //判断缓存中是否含有这张图片,没有的话去网络下载图片
 - // if (bitmap == null) {
 - new Thread(new Runnable() {
 - @Override
 - public void run() {
 - Bitmap bitmap = getBitmapFromURL(url);
 - //把下载下来的图片加到缓存中
 - if (bitmap != null) {
 - addBitmapToCache(url, bitmap);
 - }
 - Message message = new Message();
 - // message.obj = bitmap;
 - //为了保证ImageView与这时候传递过来的图像一一对应的关系
 - message.obj = new ImgHolder(imageView, bitmap, url);
 - message.what = URL_BITMAP;
 - mHandler.sendMessage(message);
 - }
 - }).start(); //记得start();
 - // } else {
 - // Message message = new Message();
 - // message.obj = bitmap;
 - //为了保证ImageView与这时候传递过来的图像一一对应的关系
 - // message.obj = new ImgHolder(imageView, bitmap, url);
 - // message.what = URL_BITMAP;
 - // mHandler.sendMessage(message);
 - // }
 - }
 - /**
 - * 根据rul获取bitmap
 - *
 - * @param url
 - * @return
 - */
 - private Bitmap getBitmapFromURL(String url) {
 - InputStream inputStream = null;
 - try {
 - URL urlBitmap = new URL(url);
 - HttpURLConnection urlConnection = (HttpURLConnection) urlBitmap.openConnection();
 - inputStream = new BufferedInputStream(urlConnection.getInputStream());
 - Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
 - // Thread.sleep(1000); //模拟网速慢的情况,为了更好的显示ImageView刷新多次的情况
 - urlConnection.disconnect(); //关闭http连接
 - return bitmap;
 - } catch (MalformedURLException e) {
 - e.printStackTrace();
 - } catch (IOException e) {
 - e.printStackTrace();
 - } finally {
 - try {
 - inputStream.close(); //关闭流
 - } catch (IOException e) {
 - e.printStackTrace();
 - }
 - }
 - return null;
 - }
 - /**
 - * 新建一个类,记录ImageView,bitmap和url
 - */
 - private class ImgHolder {
 - public Bitmap bitmap;
 - public ImageView imageView;
 - public String url;
 - public ImgHolder(ImageView iv, Bitmap bm, String url) {
 - this.imageView = iv;
 - this.bitmap = bm;
 - this.url = url;
 - }
 - }
 - /**
 - * 通过AsyncTask异步加载图片显示到ImageView
 - *
 - * @param imageView
 - * @param url
 - */
 - public void showImageByAsyncTask(ImageView imageView, String url) {
 - Bitmap bitmap = getBitmapFromCache(url);
 - if (bitmap == null) { //判断缓存是否有对应的图片
 - // new MyAsyncTask(imageView, url).execute(url);
 - imageView.setImageResource(R.mipmap.ic_launcher);
 - } else {
 - imageView.setImageBitmap(bitmap);
 - }
 - }
 - /**
 - * 创建MyAsyncTask内部类
 - * 通过AsyncTask异步加载图片
 - */
 - private class MyAsyncTask extends AsyncTask<String, Void, Bitmap> {
 - private ImageView mImageView;
 - private String mUrl;
 - /**
 - * 创建构造方法初始化ImagaeView
 - */
 - public MyAsyncTask(ImageView imageView, String url) {
 - mImageView = imageView;
 - mUrl = url;
 - }
 - public MyAsyncTask(String url) {
 - mUrl = url;
 - }
 - @Override
 - protected void onPreExecute() {
 - super.onPreExecute();
 - }
 - @Override
 - protected Bitmap doInBackground(String... params) {
 - String url = params[0];
 - Bitmap bitmap = getBitmapFromURL(url);
 - if (bitmap != null) {
 - addBitmapToCache(url, bitmap); //增叫图片到缓存
 - }
 - return bitmap;
 - }
 - @Override
 - protected void onPostExecute(Bitmap bitmap) {
 - super.onPostExecute(bitmap);
 - // if (mImageView.getTag().equals(mUrl)) {
 - // mImageView.setImageBitmap(bitmap);
 - // }
 - //从ListView中获取Imageview
 - ImageView imageView = (ImageView) mlistView.findViewWithTag(mUrl);
 - if (imageView != null && bitmap != null) {
 - imageView.setImageBitmap(bitmap);
 - }
 - }
 - }
 - /**
 - * 加载部分可见的图片
 - */
 - public void loadPartImageView(int start, int end) {
 - for (int i = start; i < end; i++) {
 - String url = MyAdapter.URLS[i];//得到可见项目起始中的各个url
 - //得到缓存中的Bitmap
 - Bitmap bitmap = getBitmapFromCache(url);
 - //bitmap为空就下载,非空就直接使用
 - if (bitmap == null) {
 - MyAsyncTask task = new MyAsyncTask(url);
 - task.execute(url);
 - mTasks.add(task);
 - } else {
 - //从ListView中获取Imageview
 - ImageView imageView = (ImageView) mlistView.findViewWithTag(url);
 - imageView.setImageBitmap(bitmap);
 - }
 - }
 - }
 - /**
 - * 取消当前正在运行的所有任务
 - */
 - public void CancelAllTask() {
 - if (mTasks != null) {
 - for (MyAsyncTask task :
 - mTasks) {
 - task.cancel(true);
 - }
 - }
 - }
 - }
 
                    
                
                
            
        
浙公网安备 33010602011771号