• 关于ImageLoader的一些东西


      网络图片异步加载 其实有关图片加载存在这样一个问题,图片的下载始终是一个耗时的操作,这个时候如果把图片加载放在主线程中话的是不明智的,模拟一个这样的场景, 假如在一个listview或RecyclerView中,每一个listitem中都有一张网络图片,假如不使用网络异步处理的话,滑动工作会特别卡,因为必须加载网图片后 ,才会加载下个item。除了这些,网络图片加载还存在很多优化,下面是ImageLoader对于网络图片加载的优化内容:

    • 加载过程使用异步,这里使用AsyncTask
    • 加载图片后,将图片放入缓存,不必每次都从网络上请求,节省流量,加快加载速度
    • 使用ViewHolder,这点就不必多说了
    • 监听滑动过程,其实我们知道的,在滑动的时候其实我们是没有必要加载图片的,等滑动结束的时候,加载当前页面的图片

      其实网上有很多类似的开源框架,但是为了理解其中原理,我自己写了一个ImageLoader。同时在加载过程中我自己写了一个ProgressDialog,显示效果如下

      1、关于异步加载:

      我的Demo里面使用的异步加载方法是AsyncTask,AsyncTask是一个很创建的异步方式,这里就不做太多介绍,只要在doInBackground方法中添加图片的网络加载即可,以下是代码:

    private class NewSAsyncTask extends AsyncTask<String, Void, Bitmap> {
    		private ImageView mimageView;
    		private String mUrl;
    		private int mType;
    
    		public NewSAsyncTask(ImageView imageview, String url,int type) {
    			mimageView = imageview;
    			mUrl = url;
    			mType=type;
    
    		}
    
    		@Override
    		protected Bitmap doInBackground(String... params) {
    			String url=params[0];
    			Bitmap bitmap=getBitmapFromUrl(mUrl,mType);
    			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);
    			}
    
    		}
    
    	}
    

      2、加载的图片放入缓存,或从缓存中读取图片--LruCache

      LruCache是android提供给我的一个有关于手机缓存中插入和读取数据的类,使用起来也很方便,以下是代码:

    public ImageLoaderUtil() {
    		int maxMemory = (int) Runtime.getRuntime().maxMemory();
    		int cacheSize = maxMemory / 8;
    		mcache = new LruCache<String, Bitmap>(cacheSize) {
    			@SuppressLint("NewApi")
    			@Override
    			protected int sizeOf(String key, Bitmap value) {
    				return value.getByteCount();
    			}
    		};
    	}
    
    	public void addBitmapToCache(String url, Bitmap bitmap) {
    		if (getBitmapFromCache(url) == null) {
    			mcache.put(url, bitmap);
    		}
    	}
    
    	public Bitmap getBitmapFromCache(String url) {
    		return mcache.get(url);
    
    	}
    

      上面的代码中先是获取当前手机可用的最大内容,然后取其8分之一,用于我们使用的缓存。

      3、判断手指滑动状态

      这个很简单,直接使用ListView或RecyclerView的滑动监听即可。当手指停止滑动的时候,判断当前屏幕中都显示哪些item,然后在加载这些item。这样一来,在手指滑动的过程中,不进行任何有关加载的相关操作,节省了流量,加快了加载速度,同时提升了用户体验。

      4、ImageLoader的逻辑顺序

      首先判断在LruCache中通过url判断是否有欲加载的图片,没有的话从网络上加载,并使用url和图片的键值对放入LruCache中。同时监听手机滑动,当收停止滑动的时候在进行加载,滑动过程中不进行任何加载。

      下面是ImageLoader的完整代码:

    package xml.org.today.util;
    
    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 android.annotation.SuppressLint;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.PorterDuffXfermode;
    import android.graphics.Rect;
    import android.graphics.RectF;
    import android.graphics.Bitmap.Config;
    import android.graphics.PorterDuff.Mode;
    import android.os.AsyncTask;
    import android.support.v4.util.LruCache;
    import android.widget.ImageView;
    
    public class ImageLoaderUtil {
        private LruCache<String, Bitmap> mcache;
    
        public ImageLoaderUtil() {
            int maxMemory = (int) Runtime.getRuntime().maxMemory();
            int cacheSize = maxMemory / 8;
            mcache = new LruCache<String, Bitmap>(cacheSize) {
                @SuppressLint("NewApi")
                @Override
                protected int sizeOf(String key, Bitmap value) {
                    return value.getByteCount();
                }
            };
        }
    
        public void addBitmapToCache(String url, Bitmap bitmap) {
            if (getBitmapFromCache(url) == null) {
                mcache.put(url, bitmap);
            }
        }
    
        public Bitmap getBitmapFromCache(String url) {
            return mcache.get(url);
    
        }
    
        /**
         * 异步加载网络图片
         *
         * @param imageview
         * @param url
         * @param type      1、圆角图片
         */
        public void getImageByAsyncTask(ImageView imageview, String url, int type) {
            Bitmap bitmap = getBitmapFromCache(url);
            if (bitmap == null) {
                new NewSAsyncTask(imageview, url, type).execute(url);
            } else {
                imageview.setImageBitmap(bitmap);
            }
    
        }
    
        private class NewSAsyncTask extends AsyncTask<String, Void, Bitmap> {
            private ImageView mimageView;
            private String mUrl;
            private int mType;
    
            public NewSAsyncTask(ImageView imageview, String url, int type) {
                mimageView = imageview;
                mUrl = url;
                mType = type;
    
            }
    
            @Override
            protected Bitmap doInBackground(String... params) {
                String url = params[0];
                Bitmap bitmap = getBitmapFromUrl(mUrl, mType);
                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);
                }
    
            }
    
        }
    
        public Bitmap getBitmapFromUrl(String urlString, int type) {
            Bitmap bitmap;
            Bitmap outbitmap;
            InputStream is = null;
            try {
                URL url = new URL(urlString);
                try {
                    HttpURLConnection connection = (HttpURLConnection) url
                            .openConnection();
                    is = new BufferedInputStream(connection.getInputStream());
                    bitmap = BitmapFactory.decodeStream(is);
                    if (type == 1) {
                        outbitmap = toRoundBitmap(bitmap);
                    } else {
                        outbitmap = bitmap;
                    }
    
                    connection.disconnect();
                    return outbitmap;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } finally {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }
    
        public static Bitmap toRoundBitmap(Bitmap bitmap) {
            Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
                    bitmap.getHeight(), Config.ARGB_8888);
            Canvas canvas = new Canvas(output);
            Paint paint = new Paint();
            int width = bitmap.getWidth();
            int height = bitmap.getHeight();
            Rect rect;
            if (width >= height) {
                rect = new Rect((width - height) / 2, 0, (width - height) / 2
                        + height, height);
            } else {
                rect = new Rect(0, (height - width) / 2, width, width
                        + (height - width) / 2);
            }
            RectF rectF = new RectF(rect);
            canvas.drawOval(rectF, paint);
            paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
            canvas.drawBitmap(bitmap, rect, rectF, paint);
            return output;
        }
    }
    

      调用的方式也很简单:

    ImageLoaderUtil mImageLoaderUtil=new ImageLoaderUtil();
    mImageLoaderUtil.getImageByAsyncTask(mView,mUrl,1);
    

      上面的代码中mView是欲加载图片的ImageView,mUrl是图片的远程地址,1代表欲加载圆角图片。

      上面代码的github地址是:https://github.com/jiushi555/ImageLoaderDemo。

  • 相关阅读:
    postman简单传参,上个接口的返回值作为下个接口的入参。
    python 给定URL 如何获取其内容,并将其保存至HTML文档。
    外键关联on_delete参数含义
    excel导入与导出
    序列化关系
    使用框架的各种代码示例
    国产celery简单使用
    selecte_related 函数优化查询
    django 之 配置文件
    类与缓存问题 类与属性的关系
  • 原文地址:https://www.cnblogs.com/YaoJianXun/p/5796433.html
Copyright © 2020-2023  润新知