实例完成Universal_Iamge_loader框架实现android图片的缓存


一 认识Universal_Image_Loader

Android应用必定会涉及异步任务下载图片,如果不做图片的缓存的话,每次打开应用都从服务器下载数据,势必消耗用户大量的流量,烧客户流量的钱必定会引起用户的反感,另一方面如果没有网了,不能回顾之前下载过的图片,还加载不出了界面,体验感极其不好,所以做图片的缓存,更新就非常有必要了。而如果开发设计这个缓存要考虑很多方面问题:多线程下载,内存溢出,缓存不能更新等诸多问题,这时安卓强大的开源功能开始展露头角了:一系列的图片的加载框架应用而生,而Universal_Image_Loader 就是使用非常普遍,正如其名所表达的了
特点:
1 多线程下载图片 
2 强大的配置功能:通过构建者设计模式,可以设计线程池大小,缓存策略,图片显示等
3 三级缓存机制:内存 ,文件系统,sd卡缓存
4 可以对下载过程监听 ,实施操作:可以停止下载,重新下载等操作


二 案例演示:一步一步详细操作

1 在Android 项目中:在dependence 的编译添加
dependencies {
..
 compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
}
点击 sync编译自动下载
universal-image-loader
架包到工程中

2 在清单文件中添加网络请求的权限和读写存储的权限
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

3 新建一个类ImageLoadUtil维护ImageLoad的使用
public class ImageLoadUtils {
    public static final int MAX_DISK_CACHE = 1024 * 1024 * 50;//最大的空间大小
    public static final int MAX_MEMORY_CACHE = 1024 * 1024 * 10;//最大的内存大小

    private static ImageLoader imageLoader;

    /**
     * 单例设计模式
     * @return
     */
    public static ImageLoader getImageLoader(){
        if (imageLoader == null){
            synchronized (ImageLoadUtils.class){
                if (imageLoader == null){
                    imageLoader = ImageLoader.getInstance();
                }
            }
        }
        return imageLoader;
    }

    public static void initImageLoader(Context context){
        ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(context);
        config.threadPoolSize(4);//线程池的大小
        config.threadPriority(Thread.NORM_PRIORITY);//设置线程的优先级
        config.memoryCacheSize(MAX_MEMORY_CACHE);//设置最大缓存容量
        config.denyCacheImageMultipleSizesInMemory();//设置图片的尺寸只有一种
        config.diskCacheFileNameGenerator(new Md5FileNameGenerator());//创建Md5方式为文件命名
        config.diskCacheSize(MAX_DISK_CACHE);
        config.tasksProcessingOrder(QueueProcessingType.LIFO);
        config.diskCache(new UnlimitedDiskCache
                (new File(Environment.getExternalStorageDirectory()+"/ImageLoader/cache")));
        if (BuildConfig.DEBUG){
            config.writeDebugLogs();
        }
        getImageLoader().init(config.build());
    }

    public static void displayImage(String url, ImageView target, DisplayImageOptions options){
        imageLoader.displayImage(url,target,options);
    }

}

4  新建一个类MyApp继承Application,确保ImageLoader只初始化一次
public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        initImageLoader(getApplicationContext());
    }
}
并在清单文件中为Application注册该Application的名字为MyApp
 <application
        android:name=".MyApp"
.....
/>
5 定义布局:
activity_main:放一个ListView展示图片
 <ListView
        android:id="@+id/list_view_main_lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

为listItem设置布局:新建布局文件image_item_loader
<ImageView
        android:id="@+id/image"
        android:layout_width="72dp"
        android:layout_height="72dp"
        android:layout_margin="3dp"
        android:adjustViewBounds="true"
        android:scaleType="centerCrop" />

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="start|center_vertical"
        android:layout_marginLeft="20dp"
        android:textSize="22sp" />

6  在MainActivity中加载图片
public class MainActivity extends AppCompatActivity {

    public static final String[] IMAGES = new String[] {
            "http://www.1688wan.com/allimgs/img_iapp/201609/_1473225269861.png",
            "http://www.1688wan.com/allimgs/img_iapp/201608/_1470736124114.png",
            "http://www.1688wan.com/allimgs/img_iapp/201609/_1473225269861.png",
            "http://www.1688wan.com/allimgs/img_iapp/201608/_1470736124114.png",
            "http://www.1688wan.com/allimgs/img_iapp/201609/_1473225269861.png",
            "http://www.1688wan.com/allimgs/img_iapp/201608/_1470736124114.png",
            "http://www.1688wan.com/allimgs/img_iapp/201609/_1473225269861.png",
            "http://www.1688wan.com/allimgs/img_iapp/201608/_1470736124114.png",
            "http://www.1688wan.com/allimgs/img_iapp/201609/_1473225269861.png",
            "http://www.1688wan.com/allimgs/img_iapp/201608/_1470736124114.png",
            "http://img.zcool.cn/community/03378c3554c7a5e00000158fc5f68ad.jpg"
           };
    private ListView mListView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }
    private void initView() {
        mListView = (ListView) findViewById(R.id.list_view_main_lv);
        mListView.setAdapter(new ImageAdapter(this));
    }

    /**
     * 当活动销毁时,清除缓存,停止ImageLoader中的线程任务
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        AnimateFirstDisplayListener.displayedImages.clear();
        ImageLoader.getInstance().clearMemoryCache();
        ImageLoader.getInstance().stop();
    }

    static class ImageAdapter extends BaseAdapter{
        private static final String[] IMAGE_URLS = MainActivity.IMAGES;

        private LayoutInflater inflater;
        private ImageLoadingListener animateFirstListener = new AnimateFirstDisplayListener();

        private DisplayImageOptions options;

        ImageAdapter(Context context) {
            inflater = LayoutInflater.from(context);

            options = new DisplayImageOptions.Builder()
                    .showImageOnLoading(R.drawable.hint)//设置图片在下载期间显示的图片
                    .showImageForEmptyUri(R.drawable.no)//设置图片Uri为空或是错误的时候显示的图片
                    .showImageOnFail(R.drawable.yes)//设置图片加载/解码过程中错误时候显示的图片
                    .delayBeforeLoading(100)//设置延时多少时间后开始下载
                    .cacheInMemory(true)//设置下载的图片是否缓存在内存中
                    .cacheOnDisk(true)// 设置下载的资源是否缓存在SD卡中
                    .considerExifParams(true)// 是否考虑JPEG图像EXIF参数(旋转,翻转)
                    .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2)//设置图片以何种编码方式显示
                    .bitmapConfig(Bitmap.Config.RGB_565) // 设置图片的解码类型
                    .displayer(new RoundedBitmapDisplayer(20))//是否设置为圆角,弧度为多少
                    .displayer(new FadeInBitmapDisplayer(1000))//是否图片加载好后渐入的动画时间
                    .build();
        }

        @Override
        public int getCount() {
            return IMAGE_URLS.length;
        }

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

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

        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            View view = convertView;
            final ViewHolder holder;
            if (convertView == null) {
                view = inflater.inflate(R.layout.item_image_loader, parent, false);
                holder = new ViewHolder();
                holder.image = (ImageView) view.findViewById(R.id.image);
                view.setTag(holder);
            } else {
                holder = (ViewHolder) view.getTag();
            }


            ImageLoader.getInstance().displayImage(IMAGE_URLS[position], holder.image, options, animateFirstListener);

            return view;
        }
    }

    static class ViewHolder {
        ImageView image;
    }

    private static class AnimateFirstDisplayListener extends SimpleImageLoadingListener {

        static final List<String> displayedImages = Collections.synchronizedList(new LinkedList<String>());

        @Override
        public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
            if (loadedImage != null) {
                ImageView imageView = (ImageView) view;
                boolean firstDisplay = !displayedImages.contains(imageUri);
                if (firstDisplay) {
                    FadeInBitmapDisplayer.animate(imageView, 500);
                    displayedImages.add(imageUri);
                }
            }
        }
    }
}

运行后,成功加载图片,即使没有网了依然可以看到图片,说明成功缓存了。




























评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值