感谢 http://adk.tumblr.com/post/13069401302/outofmemoryerror-imageview-and-transitiondrawable-a
1、实现ImageView的渐隐渐现的效果
实现两张图片渐隐渐现的过渡效果,大家马上回想到使用TransitionDrawable来实现,这方面的例子网上挺多:
比在布局文件中使用translation实现
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/image_expand" />
<item android:drawable="@drawable/image_collapse" />
</transition>
在Java中使用代码:
Resources res = getResources();
TransitionDrawable transition = (TransitionDrawable)res.getDrawable(R.drawable.expand_collapse);
ImageView image = (ImageView) findViewById(R.id.toggle_image);
image.setImageDrawable(transition);
transition.startTransition(1000);
或者使用下面代码实现:
TransitionDrawable mTransitionDrawable = new TransitionDrawable(new Drawable[]{
view.getDrawable(),
new BitmapDrawable(bitmap)
});
mTransitionDrawable.setCrossFadeEnabled(true);
mTransitionDrawable.startTransition(500);
view.setImageDrawable(mTransitionDrawable);
最近在项目中的使用第二钟方法来实现在gridview中显示大量从网络下载的图片显示的情况。gridview中最多要显示2000多种图片,就在adapter的getView方法中开启synctask来下载图片,下载完成后就更新到UI,并实现渐隐渐现的动画效果。
注意到这里的问题了,2000多张图片,预示着要生成2000多个TransitionDrawable 的临时变量,通常情况下是显示不到20张就OutOfMemory了。在http://adk.tumblr.com/post/13069401302/outofmemoryerror-imageview-and-transitiondrawable-a一文中作者提到了,是存在内存泄露的情况了。最后采取了文中的方法,成功实现了想要的效果。
2、代码:
这里先从ImageView中取出它包含的Drawable,看是属于TransitionDrawable还是属于BitmapDrawable的实例,如果属于TransitionDrawable,那么就取出它的第二个layer的图片作为下一个动画的第一个layer,把将要显示的图片作为第二个layer。如果属于BitmapDrawable那就说明还没有为该gridview创建TransitionDrawable,那么就创建一个。并把该BitmapDrawable作为下一个动画的第一个layer,把将要显示的图片作为第二个layer。
由于GridView仅保存几个ImageView实例来循环使用来显示图片,因此并不会频繁的创建TransitionDrawable,这样就不会内存泄露造成OOM了。
Drawable oldDrawable = view.getDrawable();
BitmapDrawable oldBitmapDrawable = null;
TransitionDrawable oldTransitionDrawable=null;
if(oldDrawable instanceof TransitionDrawable){
oldTransitionDrawable = (TransitionDrawable)oldDrawable;
oldBitmapDrawable =(BitmapDrawable)oldTransitionDrawable.findDrawableByLayerId(oldTransitionDrawable.getId(1));
//oldBitmapDrawable =(BitmapDrawable) (oldTransitionDrawable).getDrawable(1);
}
else if(oldDrawable instanceof BitmapDrawable){
oldBitmapDrawable = (BitmapDrawable) oldDrawable;
}
else{
Log.e(TAG, "Some Error in setImageSourceAndDoAni");
}
if(oldTransitionDrawable==null){
oldTransitionDrawable = new TransitionDrawable(new Drawable[]{
oldBitmapDrawable,
new BitmapDrawable(bitmap)
});
//----------very important!!!
oldTransitionDrawable.setId(0, 0);
oldTransitionDrawable.setId(1, 1);
//----------
oldTransitionDrawable.setCrossFadeEnabled(true);
view.setImageDrawable(oldTransitionDrawable);
}
else{
oldTransitionDrawable.setDrawableByLayerId(oldTransitionDrawable.getId(0), oldBitmapDrawable);
oldTransitionDrawable.setDrawableByLayerId(oldTransitionDrawable.getId(1), new BitmapDrawable(bitmap) );
}
oldTransitionDrawable.startTransition(800);
特别注意在使用过程中下面两行代码:
oldTransitionDrawable.setId(0, 0);
oldTransitionDrawable.setId(1, 1);
如果不设置的话,你会发现getId(0)和getId(1)都会是0,那么setDrawableByLayerId就会达不到想要的效果。