Android开发中我们会经常遇到图片过多或操作不当造成OOM异常,有时虽然是解决了这个问题但却会影响程序的运行效率,例如:当用户在快速滑动滚动条的过程中,我们程序在仍在艰难的加载服务器端的图片,这样给用户造成了极不好的体验。其实网络上关于图片的异步加载和缓存的讲解很多,但是其实,写一个这方面的程序还是比较麻烦的,要考虑多线程,缓存,内存溢出等很多方面,针对这一光大开发者都会遇到的问题,一些牛人们已经帮我们解决了这一问题,今天我为大家介绍一款很流行的开源类库,可以很很好的解决大家的烦恼!

   

一.介绍:

   Android-Universal-Image-Loader是一个开源的UI组件程序,该项目的目的是提供一个可重复使用的仪器为异步图像加载,缓存和显示。

   在GitHub上面的一个开源类库(官方下载:https://github.com/nostra13/Android-Universal-Image-Loader


  特点:

       1.多线程的图像加载;

       2.图片异步加载缓存机制,包括内存缓存(软引用)及本地缓存;

       3.动态对ImageLoader的配置(线程池的大小,HTTP选项,内存和光盘高速缓存方式,显示图像,以及其他选项);

       4.对加载过程实现监听和事件处理;

       5.能够配置加载图片的显示选项,包括图片圆角处理和加载完成显示动画等;

(官方截图)



二.使用

  1.将下载下来的zip包,解压开得到如下图所示文件夹

  2.将universal-p_w_picpath-loader-1.8.6-with-sources.jar导入到新建的项目中,参考sample中的例子进行使用即可。为了让新手们快速掌握这里我简单讲解一下它的使用过程(使用该类库中ImageLoader加载图片,ListView、GridView、ViewPager)


Demo项目图解:


   

    2.1.在程序启动时,用户可以根据自己的情况初始化ImageLoaderConfiguration

public class MyApplication extends Application{    @Override    public void onCreate() {        super.onCreate();        initImageLoader(getApplicationContext());    }    /**初始化图片加载类配置信息**/    public static void initImageLoader(Context context) {        // This configuration tuning is custom. You can tune every option, you may tune some of them,        // or you can create default configuration by        //  ImageLoaderConfiguration.createDefault(this);        // method.        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)            .threadPriority(Thread.NORM_PRIORITY - 2)//加载图片的线程数            .denyCacheImageMultipleSizesInMemory() //解码图像的大尺寸将在内存中缓存先前解码图像的小尺寸。            .discCacheFileNameGenerator(new Md5FileNameGenerator())//设置磁盘缓存文件名称            .tasksProcessingOrder(QueueProcessingType.LIFO)//设置加载显示图片队列进程            .writeDebugLogs() // Remove for release app            .build();        // Initialize ImageLoader with configuration.        ImageLoader.getInstance().init(config);    }}

别忘了在AndroidManifest.xml中

android:name=".MyApplication"


  2.2.在MainActivity中我们做的仅仅是跳转到对应的界面,下面看一下ListView中的具体使用,剩下两个自己看一下Demo,原理一样。

ImageListActivity:

/** * listView中使用ImageLoader * @author ZHF * */public class ImageListActivity extends AbsListViewBaseActivity {    DisplayImageOptions options; //配置图片加载及显示选项    String[] p_w_picpathUrls;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.ac_p_w_picpath_list);        //获取url数组        Bundle bundle = getIntent().getExtras();        p_w_picpathUrls = bundle.getStringArray(Extra.IMAGES);        //配置图片加载及显示选项(还有一些其他的配置,查阅doc文档吧)        options = new DisplayImageOptions.Builder()            .showStubImage(R.drawable.ic_stub)    //在ImageView加载过程中显示图片            .showImageForEmptyUri(R.drawable.ic_empty)  //p_w_picpath连接地址为空时            .showImageOnFail(R.drawable.ic_error)  //p_w_picpath加载失败            .cacheInMemory(true)  //加载图片时会在内存中加载缓存            .cacheOnDisc(true)   //加载图片时会在磁盘中加载缓存            .displayer(new RoundedBitmapDisplayer(20))  //设置用户加载图片task(这里是圆角图片显示)            .build();        listView = (ListView) findViewById(android.R.id.list);        //绑定适配器        listView.setAdapter(new ItemAdapter());        listView.setOnItemClickListener(new OnItemClickListener() {            @Override            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {                startImagePagerActivity(position);            }        });    }    @Override    public void onBackPressed() {        AnimateFirstDisplayListener.displayedImages.clear();        super.onBackPressed();    }    private void startImagePagerActivity(int position) {        Intent intent = new Intent(this, ImagePagerActivity.class);        intent.putExtra(Extra.IMAGES, p_w_picpathUrls);        intent.putExtra(Extra.IMAGE_POSITION, position);        startActivity(intent);    }    /**自定义图片适配器**/    class ItemAdapter extends BaseAdapter {        private ImageLoadingListener animateFirstListener = new AnimateFirstDisplayListener();        private class ViewHolder {            public TextView text;            public ImageView p_w_picpath;        }        @Override        public int getCount() {            return p_w_picpathUrls.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 = getLayoutInflater().inflate(R.layout.item_list_p_w_picpath, parent, false);                holder = new ViewHolder();                holder.text = (TextView) view.findViewById(R.id.text);                holder.p_w_picpath = (ImageView) view.findViewById(R.id.p_w_picpath);                view.setTag(holder);            } else {                holder = (ViewHolder) view.getTag();            }            holder.text.setText("Item " + (position + 1));            //Adds display p_w_picpath task to execution pool. Image will be set to ImageView when it's turn.            p_w_picpathLoader.displayImage(p_w_picpathUrls[position], holder.p_w_picpath, options, animateFirstListener);            return view;        }    }    /**图片加载监听事件**/    private static class AnimateFirstDisplayListener extends SimpleImageLoadingListener {        static final List displayedImages = Collections.synchronizedList(new LinkedList());        @Override        public void onLoadingComplete(String p_w_picpathUri, View view, Bitmap loadedImage) {            if (loadedImage != null) {                ImageView p_w_picpathView = (ImageView) view;                boolean firstDisplay = !displayedImages.contains(p_w_picpathUri);                if (firstDisplay) {                    FadeInBitmapDisplayer.animate(p_w_picpathView, 500); //设置p_w_picpath隐藏动画500ms                    displayedImages.add(p_w_picpathUri); //将图片uri添加到集合中                }            }        }    }}

说明:

   1.使用ImageLoader加载图片,只要在Adapter的getView方法中调用displayImage方法完成了异步列表图片加载,其中options是之前定义的图片加载和显示选项(我们这里使用的是RoundedBitmapDisplayer圆角图片显示),animateFirstListener是当图片第一次加载的监听事件,目的在于显示一个淡入的显示效果动画,可以添加其他事件

   2.进本人测试,官网例子中的Constant类中图片的Uri在手机中链接很慢,完全达不到效果,之后我将其更改为其他一系列图片的Uri,便于观察效果!


效果图:

   


  最后,大家在使用的时候记得关注一下在/sdcard/Android/data/[package_name]/cache目录下的缓存的文件。记得定期清理缓存,否则时间一长,SD卡就会被占满了,同时也可以在ImageLoaderConfiguration中配置SD的缓存策略,限制缓存文件数量(memoryCacheSizePercentage),限制缓存文件最大尺寸(memoryCacheSize)等选项。


Demo源码已上传!

 



更多相关文章

  1. Android(安卓)So加载的路径选择以及注意选项
  2. Android之Android(安卓)apk动态加载机制的研究
  3. android 帧动画的替代方案
  4. android处理拍照旋转问题及带来的对内存占用的思考
  5. Android用AsyncTask来下载图片及用AsyncTask的好处
  6. 以 Okhttp3源码 为例 ------ 图解 缓存机制 的原理和实现(上)
  7. Android实现图片滚动控件,含页签功能,让你的应用像淘宝一样炫起来
  8. Android(安卓)使用腾讯的TBS浏览器X5内核的集成加载pdf等文件
  9. Android(安卓)解码播放GIF图像

随机推荐

  1. 跨进程存取数据
  2. 了解Context
  3. Android(安卓)WebView请求,保存cookie,判断
  4. Android(安卓)AndroidStudio环境下控制状
  5. android Dialog给Activity 传参
  6. android的listview item点击详解
  7. Gtalk登陆
  8. Android下建立数据库
  9. BigImageViewer
  10. Android主流框架学习之旅