android 网络图片异步加载

原理:

1.通过URL下载网络图片

2.创建异步类AsyncTask执行异步操作

3.将图片写入内存或缓存

4.通知UI更新

重点:

1.使用LruCache缓存Bitmap

2.将图片写入本地下次调用无需下载

3.使用Set集合管理下载任务

4.重写滑动监听实现同步下载


注:详细请看注释



1.图片加载类

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;
import android.util.LruCache;
import android.widget.GridView;
import android.widget.ImageView;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;


public class LoaderImage {
    //图片缓存空间
    private LruCache<String, Bitmap> mLruCache;
    private GridView mGridView;
    //下载任务管理集合
    private Set<NewAsyncTask> mTask;

    public LoaderImage(GridView gridView) {
        mGridView = gridView;
        mTask = new HashSet<>();
        //为LruCache初始化空间(系统内存的1/8)
        int maxMemory = (int) Runtime.getRuntime().maxMemory();
        int cacheMemory = maxMemory / 8;
        mLruCache = new LruCache<String, Bitmap>(cacheMemory) {
            @Override
            protected int sizeOf(String key, Bitmap value) {
                //每个Bitmap所占内存
                return value.getRowBytes() * value.getHeight();
            }
        };
    }

    private void addBitmapToLruCache(String path, Bitmap bm) {
        if (mLruCache.get(path) == null) {
            if (bm != null) {
                mLruCache.put(path, bm);
            }
        }
    }

    public Bitmap getBitmapByURL(String path) {
        Log.d("getBitmapByURL", "--- " + path);
        URL myFileURL;
        Bitmap bitmap = null;
        try {
            myFileURL = new URL(path);
            HttpURLConnection conn = (HttpURLConnection) myFileURL.openConnection();
            conn.setConnectTimeout(6000);
            //连接设置获得数据流
            conn.setDoInput(true);
            //不使用缓存
            conn.setUseCaches(false);
            InputStream is = conn.getInputStream();
            bitmap = BitmapFactory.decodeStream(is);
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap;
    }

    //从LruCache中获取图片
    public void showImageByAsyncTask(ImageView imageView, String path) {
        Bitmap bm = mLruCache.get(path);
        if (bm != null) {
            imageView.setImageBitmap(bm);
        } else {
            //自定义未加载完成时的图片
            imageView.setImageResource(R.mipmap.ic_launcher);
        }
    }

    //将当前屏幕的图片加入下载任务
    public void loadImages(int mStart, int mEnd) {
        for (int i = mStart; i < mEnd; i++) {
            //ImageYL.Urls[i]           
            String path = ImageYL.Urls[i];
            Bitmap bm = mLruCache.get(path);
            if (bm == null) {
                NewAsyncTask task = new NewAsyncTask(path);
                task.execute(path);
                mTask.add(task);
            } else {
                ImageView imageView = (ImageView) mGridView.findViewWithTag(path);
                imageView.setImageBitmap(bm);
            }
        }
    }

    //用户滑动时取消下载
    public void cancleAllTasks() {
        if (mTask != null) {
            for (NewAsyncTask task : mTask) {
                task.cancel(false);
            }
        }
    }

    //图片异步下载类
    private class NewAsyncTask extends AsyncTask<String, Void, Bitmap> {
        private String mPath;

        public NewAsyncTask(String path) {
            mPath = path;
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            Bitmap bm = null;
            //判断SD卡是否存在(下载图片到本地/仅缓存)
            if (ExistSDCard()) {
                String path = downloadPic(params[0]);
                //压缩图片
                bm = ImageUtil.decodeSampledBitmapFromPath(path);
            } else {
                bm = getBitmapByURL(params[0]);
            }
            if (bm != null) {
                addBitmapToLruCache(mPath, bm);
            }
            return bm;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            ImageView imageView = (ImageView) mGridView.findViewWithTag(mPath);
            if (imageView != null && bitmap != null) {
                imageView.setImageBitmap(bitmap);
            }
            mTask.remove(this);
        }
    }

    //判断有木有SD卡
    private boolean ExistSDCard() {
        if (android.os.Environment.getExternalStorageState().equals(
                android.os.Environment.MEDIA_MOUNTED)) {
            return true;
        } else
            return false;
    }

    //图片保存到本地
    public String downloadPic(String relativePath) {
        String filePath = null;
        URL picUrl;
        HttpURLConnection conn = null;
        InputStream fileIn = null;
        BufferedOutputStream fileOut = null;
        try {
            filePath = Environment.getExternalStorageDirectory()
                    + File.separator + relativePath;
            File picFile = new File(filePath);
            if (picFile.exists()) {
                return filePath;
            }
            File dir = new File(picFile.getParent());
            if (!dir.isDirectory() || !dir.exists()) {
                dir.mkdirs();
            }
            Log.d("--", "downloadPic,dir:" + dir.getAbsolutePath()
                    + ",picFile:" + picFile.getAbsolutePath());
            picFile.createNewFile();
            picUrl = new URL(relativePath);

            conn = (HttpURLConnection) picUrl.openConnection();
            fileIn = conn.getInputStream();
            fileOut = new BufferedOutputStream(
                    new FileOutputStream(picFile));
            byte[] buf = new byte[1024];
            int r = 0, all = 0;
            while ((r = fileIn.read(buf)) > 0) {
                fileOut.write(buf, 0, r);
                all += r;
            }

            Log.d("--", "read file  : " + relativePath + ",len: " + all);
            fileOut.close();
            fileIn.close();

        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常!" + e);
            e.printStackTrace();
        } finally {
            if (fileIn != null) {
                try {
                    fileIn.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fileOut != null) {
                try {
                    fileOut.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                conn.disconnect();
            }
        }
        return filePath;
    }

}



2.图片压缩类


import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;


public class ImageUtil {

    //图片压缩(默认分辨率720*1280)
    public static Bitmap decodeSampledBitmapFromPath(String path) {
        BitmapFactory.Options options=new BitmapFactory.Options();
        options.inJustDecodeBounds=true;
        BitmapFactory.decodeFile(path, options);
        options.inSampleSize=caculateInSampleSize(options,720f,1280f);
        options.inJustDecodeBounds=false;
        Bitmap bm=BitmapFactory.decodeFile(path,options);
        return bm;
    }
    //获取压缩比例
    public static int caculateInSampleSize(BitmapFactory.Options options, float reqWidth, float reqHeight) {
        int width=options.outWidth;
        int height=options.outHeight;
        int inSampleSize=1;
        if(width>reqWidth||height>reqHeight){
            int widthRadio=Math.round(width*1.0f/reqWidth);
            int heightRadio=Math.round(height*1.0f/reqHeight);
            inSampleSize=Math.max(widthRadio,heightRadio);
        }
        return inSampleSize;
    }
}



3.重写适配器


private class GridViewAdapter extends BaseAdapter implements AbsListView.OnScrollListener {

    private int mStart, mEnd;
    private boolean mFristin;

    public GridViewAdapter(GridView gridView) {
        loaderImage = new LoaderImage(gridView);
        mFristin = true;
        gridView.setOnScrollListener(this);
    }

    @Override
    public int getCount() {
        return image_path.size();
    }

    @Override
    public String getItem(int position) {
        return image_path.get(position);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.item_grid, null);
            holder = new ViewHolder();
            holder.imageView = (ImageView) convertView.findViewById(R.id.id_ima);
            holder.textView = (TextView) convertView.findViewById(R.id.id_text);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        String path = image_path.get(position);
        holder.imageView.setTag(path);
        loaderImage.showImageByAsyncTask(holder.imageView, path);
        return convertView;
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        //根据用户滑动来决定是否加载图片
        if (scrollState == SCROLL_STATE_IDLE) {
            loaderImage.loadImages(mStart, mEnd);
        } else {
            loaderImage.cancleAllTasks();
        }
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        mStart = firstVisibleItem;
        mEnd = firstVisibleItem + visibleItemCount;
        //第一次打开加载当前界面图片
        if (mFristin && visibleItemCount > 0) {
            loaderImage.loadImages(mStart, mEnd);
            mFristin = false;
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值