android中对图片显示加载如果处理不好,易出现OOM。因最近项目用到,就对好用效果好的开源框架Android-Universal-Image-Loader研究下,
它提供了一个可重复使用的仪器为异步图像加载,缓存和显示。
1、首先需要在自定义的application中设置全局性的配置,主要有线程类、缓存大小、磁盘大小、图片下载与解析、日志方面的配置。
(参数只能配置一次,如多次配置,则默认第一次的配置参数)
public class BaseApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
initImageLoader(getApplicationContext());
}
private void initImageLoader(Context context) {
ImageLoaderConfiguration configuration=new ImageLoaderConfiguration.Builder(context)
// 线程优先级
.threadPriority(Thread.NORM_PRIORITY-2)
//强制UIL在内存中不能存储内容相同但大小不同的图像
.denyCacheImageMultipleSizesInMemory()
//将保存的时候的URI名称用MD5
.discCacheFileNameGenerator(new Md5FileNameGenerator())
.tasksProcessingOrder(QueueProcessingType.LIFO)
.writeDebugLogs()
.build();
//初始化操作
ImageLoader.getInstance().init(configuration);
}
}
2、获取ImageLoader,具体下载图片,缓存图片,显示图片的具体执行类
因加载的图片可以缓存到内存或sd卡中,所以有专门的方法清除缓存。
public class BaseActivity extends Activity {
//获取ImageLoader的实例
protected ImageLoader imageLoader=ImageLoader.getInstance();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
/**
* 清除内存缓存
*
* @创建日期 2016-8-8
*
* @返回值 void
*
*/
protected void clearMemoryCache() {
imageLoader.clearMemoryCache();
}
/**
* 清除SD卡中的缓存
*
* @创建日期 2016-8-8
*
* @返回值 void
*
*/
protected void clearDiscCache() {
imageLoader.clearDiscCache();
}
}
3、设置DisplayImageOptions用于指导每一个Imageloader根据网络图片的状态(空白、下载错误、正在下载)显示对应的图片,是否将缓存加载到磁盘上,下载完后对图片进行具体的设置处理
例子是gridview显示从网络、drawable文件夹、assets、sd(不能加载9patch),新增加载视频缩略图获取图片显示
public class ImageGridActivity extends BaseActivity {
private GridView mGridview;
private DisplayImageOptions options;
private String[] imageUrls=new String[]{
"http://simpozia.com/pages/images/stories/windows-icon.png",
"http://simpozia.com/pages/images/stories/windows-icon.png",
"http://www.krify.net/wp-content/uploads/2011/09/Macromedia_Flash_dock_icon.png",
"drawable://" + R.drawable.ic_launcher,
"assets://banner01.jpg",
"file:///sdcard/Universal Image Loader @#&=+-_.,!()~'%20.png",
"",//空
"content://media/external/images/media/13 // from content provider"
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_grid);
options = new DisplayImageOptions.Builder()
// 设置图片下载期间显示的图片
.showStubImage(R.drawable.ic_stub)
// 设置图片Uri为空或是错误的时候显示的图片
.showImageForEmptyUri(R.drawable.ic_empty)
//设置图片加载或解码过程中发生错误显示的图片
.showImageOnFail(R.drawable.ic_error)
// 设置下载的图片是否缓存在内存中
.cacheInMemory(true)
// 设置下载的图片是否缓存在SD卡中
.cacheOnDisc(true)
// 设置成圆角图片
.displayer(new RoundedBitmapDisplayer(20))
.build();
mGridview=(GridView) findViewById(R.id.gridview);
mGridview.setAdapter(new ImageAdapter());
mGridview.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
startImagePagerActivity(position);
}
});
}
//跳转到查看图片详情的页面
private void startImagePagerActivity(int position) {
Intent intent = new Intent(this, ImagePagerActivity.class);
intent.putExtra("imageurls", imageUrls);
intent.putExtra("position", position);
startActivity(intent);
}
public class ImageAdapter extends BaseAdapter{
@Override
public int getCount() {
return imageUrls.length;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ImageView imageView;
if (convertView == null) {
imageView = (ImageView) getLayoutInflater().inflate(R.layout.item_grid_image, parent, false);
} else {
imageView = (ImageView) convertView;
}
//显示图片
imageLoader.displayImage(imageUrls[position], imageView, options);
return imageView;
}
}
}
4、显示图片的方法,常用方法
1、 ImageLoader.getInstance().displayImage(uri, imageView);
2、 ImageLoader.getInstance().displayImage(uri, imageView, options);
3、 ImageLoader.getInstance().displayImage(uri, imageView, listener); 加载带监听的一个图片
4、 ImageLoader.getInstance().displayImage(uri, imageView, options, listener); 加载自定义配置且带监听的一个图片
5、 ImageLoader.getInstance().displayImage(uri, imageView, options, listener, progressListener); 加载自定义配置且带监听和进度条的一个图片
参数解析:
imageUrl 图片的URL地址
imageView 显示图片的ImageView控件
options DisplayImageOptions配置信息
listener 图片下载情况的监听
progressListener 图片下载进度的监听
点击显示图片详情:
public class ImagePagerActivity extends BaseActivity {
private DisplayImageOptions options;
private ViewPager pager;
private static final String STATE_POSITION = "STATE_POSITION";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_pager);
Bundle bundle = getIntent().getExtras();
String[] imageUrls = bundle.getStringArray("imageurls");
int pagerPosition = bundle.getInt("position", 0);
// 如果之前有保存用户数据
if (savedInstanceState != null) {
pagerPosition = savedInstanceState.getInt(STATE_POSITION);
}
options = new DisplayImageOptions.Builder()
.showImageForEmptyUri(R.drawable.ic_empty)
.showImageOnFail(R.drawable.ic_error)
.resetViewBeforeLoading(true).cacheOnDisc(true)
.imageScaleType(ImageScaleType.EXACTLY)
.bitmapConfig(Bitmap.Config.RGB_565)
.displayer(new FadeInBitmapDisplayer(300)).build();
pager=(ViewPager) findViewById(R.id.pager);
pager.setAdapter(new ImagePagerAdapter(imageUrls));
pager.setCurrentItem(pagerPosition); // 显示当前位置的View
}
@Override
public void onSaveInstanceState(Bundle outState) {
// 保存用户数据
outState.putInt(STATE_POSITION, pager.getCurrentItem());
}
private class ImagePagerAdapter extends PagerAdapter {
private String[] images;
private LayoutInflater inflater;
public ImagePagerAdapter(String[] imageUrls){
this.images=imageUrls;
inflater = getLayoutInflater();
}
@Override
public int getCount() {
return images.length;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}
@Override
public Object instantiateItem(ViewGroup view, int position) {
View imageLayout = inflater.inflate(R.layout.item_pager_image, view, false);
ImageView imageView = (ImageView) imageLayout.findViewById(R.id.image);
final ProgressBar spinner = (ProgressBar) imageLayout.findViewById(R.id.loading);
imageLoader.displayImage(images[position], imageView, options, new SimpleImageLoadingListener(){
@Override
public void onLoadingStarted(String imageUri, View view) {
spinner.setVisibility(View.VISIBLE);
}
@Override
public void onLoadingFailed(String imageUri, View view,FailReason failReason) {
super.onLoadingFailed(imageUri, view, failReason);
String message = null;
switch (failReason.getType()) {
case IO_ERROR: // 文件I/O错误
message = "Input/Output error";
break;
case DECODING_ERROR: // 解码错误
message = "Image can't be decoded";
break;
case NETWORK_DENIED: // 网络延迟
message = "Downloads are denied";
break;
case OUT_OF_MEMORY: // 内存不足
message = "Out Of Memory error";
break;
case UNKNOWN: // 原因不明
message = "Unknown error";
break;
}
Toast.makeText(ImagePagerActivity.this, message, Toast.LENGTH_SHORT).show();
spinner.setVisibility(View.GONE);
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
spinner.setVisibility(View.GONE); // 不显示圆形进度条
}
});
((ViewPager) view).addView(imageLayout, 0); // 将图片增加到ViewPager
return imageLayout;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}
@Override
public void restoreState(Parcelable state, ClassLoader loader) {
}
@Override
public Parcelable saveState() {
return null;
}
@Override
public void startUpdate(View container) {
}
}
}