afinal框架有四个部分,分别为FinalActivity、FinalBitmap、FinalDb、FinalHttp组成,分别完成Activity定义、图片加载、数据库使用、网络操作的功能,今天这篇文章主要是介绍FinalBitmap,也就是图片加载这个类的功能和使用分别进行介绍。
<一> FinalBitmap的功能特点:
①FinalBitmap模块:通过FinalBitmap,imageview加载bitmap的时候无需考虑bitmap加载过程中出现的oom和android容器快速滑动时候出现的图片错位等现象。
②FinalBitmap可以配置线程加载线程数量,缓存大小,缓存路径,加载显示动画等。
③FinalBitmap的内存管理使用lru算法,没有使用弱引用(android2.3以后google已经不建议使用弱引用,android2.3后强行回收软引用和弱引用,详情查看android官方文档),更好的管理bitmap内存。
④FinalBitmap可以自定义下载器,用来扩展其他协议显示网络图片,比如ftp等。同时可以自定义bitmap显示器,在imageview显示图片的时候播放动画等(默认是渐变动画显示)
首先在Android开发中,图片的显示可以说是必不可少的,由于Android运行平台的特点,我们在加载图片,特别是网络图片的时候,一般都会完成图片的缓存,从而减少Android系统的运行负荷。而完成图片的缓存,又分为两种,一种是完成图片的本地缓存,就是把从网络加载过的图片放在本地,这样当我们下次再次加载相同的图片的时候,我们就可以直接从本地的硬盘中获取图片,从而减少图片的加载速度,更重要的是减少流量和手机电量的损耗。
除了将图片缓存到本地之外,我们在图片加载完之后,还应该将图片缓存在我们的手机内存中,比如在Listview控件里显示网络图片,由于我们上下滑动造成item会不断的生成并显示数据,这个时候如果我们要显示图片,那么每次都要从网络这是是本地硬盘读取图片实现相当的影响性能的,因此,我们最好将刚加载好的图片,在内存中进行缓存,那么当我们上下的滑动Listview的时候,我们就可以直接从我们的内存中获取图片的引用,从而加快我们的加载速度。
一般来说,要自己实现这两种缓存方式还是挺复杂的,还好,FinalBitmap已经为我们实现了这些功能,因此,我们要做的功能就非常少了,下面,我们介绍FinalBitmap的简单使用。
private static FinalBitmap mFinalBitmap;
private FinalBitmap(Context context) {
mContext = context;
mConfig = new FinalBitmapConfig(context);
configDiskCachePath(Utils.getDiskCacheDir(context, "afinalCache").getAbsolutePath());// 配置缓存路径
configDisplayer(new SimpleDisplayer());// 配置显示器
configDownlader(new SimpleDownloader());// 配置下载器
}
/**
* 创建finalbitmap
*
* @param ctx
* @return
*/
public static synchronized FinalBitmap create(Context ctx) {
if (mFinalBitmap == null) {
mFinalBitmap = new FinalBitmap(ctx.getApplicationContext());
}
return mFinalBitmap;
}
上面是FinalBitmap的源码,我们可以看出,FinalBitmap使用的是线程安全的单例模式,因此,当我们想获取一个FinalBitmap对象的时候,我们可以这样做
获取到我们的FinalBitmap对象之后,我们就可以使用display方法来显示图片了。FinalBitmap给我们提供了好几种display方法,可以很简单的实现网络图片的加载,下面我们简单看一下
FinalBitmap bitmap = FinalBitmap.create(context);
//<span style="font-family: Arial, Helvetica, sans-serif;">获取到我们的FinalBitmap对象之后,我们就可以使用display方法来显示图片了。FinalBitmap给我们提供了好几种display方法,可以很简单的实现网络图片 的加载,下面我们简单看一下 </span>设置图片的uri地址
String uri = "http://avatar.csdn.net/C/6/8/1_bz419927089.jpg";
//初始化加载中时显示的图片
Bitmap loadingBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
//初始化加载失败显示的图片
Bitmap failBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
//第一种方式:image为要显示图片的控件
bitmap.display(image, uri);
//第二种方式:loadingBitmap为正在加载时显示的图片
bitmap.display(image, uri, loadingBitmap);
//第三种方式:config为FinalBitmap的配置对象,可以配置显示的动画,大小,加载失败图片等等
BitmapDisplayConfig config = new BitmapDisplayConfig();
config.setLoadingBitmap(loadingBitmap);
bitmap.display(image, uri, config);
//第四种方式:loadingBitmap为加载中图片,failBitmap为加载失败图片
bitmap.display(image, uri, loadingBitmap, failBitmap);
//第五种方式:我们也可以设置加载图片的大小
bitmap.display(image, uri, 100, 100);
//第六种方式:设置加载图片的大小以及加载中和加载失败的图片
bitmap.display(image, uri, 100, 100, loadingBitmap, failBitmap);
FinalBitmap在使用的时候可以进行设置
finalBitmap = FinalBitmap.create(this.getApplicationContext()); 初始化
finalBitmap.configBitmapLoadThreadSize(3);定义线程数量
finalBitmap.configDiskCachePath(this.getApplicationContext().getFilesDir().toString());设置缓存目录;
finalBitmap.configDiskCacheSize(1024 * 1024 * 10);设置缓存大小
finalBitmap.configLoadingImage(R.drawable.news_default);设置加载图片
从上面的使用我们可以看出,FinalBitmap可以说是非常简单就可以上手的,这为我们的开发节省了很多的时间。
下面,我们简单的分析一下FinalBitmap的源代码
private FinalBitmap(Context context) {
mContext = context;
mConfig = new FinalBitmapConfig(context);
configDiskCachePath(Utils.getDiskCacheDir(context, "afinalCache").getAbsolutePath());// 配置缓存路径
configDisplayer(new SimpleDisplayer());// 配置显示器
configDownlader(new SimpleDownloader());// 配置下载器
}
上面这段代码是FinalBitmap的构造器,我们可以看出,在初始化的时候,已经为我们配置好了图片的缓存路径,这个缓存路径我们可以通过configDiskCachePath方法来修改默认的缓存路径,我的测试机上默认的缓存路径为
/storage/sdcard0/Android/data/com.example.afinatest/cache/afinalCache
除了设置我们的缓存路径,我们还可以设置缓存目录的大小,方法是
configDiskCacheSize
但是这个方法要注意的是,默认的是5M,只有设置大小为5M之上的时候,我们的设置才起作用。
除此之外,如果我们想清除我们的图片缓存,那么我们就可以通过clearDiskCache方法,把硬盘的缓存清除掉
还有一点很重要的是,在我们使用FinalBitmap的时候,我们还要在Activity的onResume、onPause、onDestroy这三个生命周期的方法中,调用FinalBitmap对应的这三个方法,从而使我们占用的资源进行很好的回收
/**
* activity onResume的时候调用这个方法,让加载图片线程继续
*/
public void onResume() {
setExitTasksEarly(false);
}
/**
* activity onPause的时候调用这个方法,让线程暂停
*/
public void onPause() {
setExitTasksEarly(true);
}
/**
* activity onDestroy的时候调用这个方法,释放缓存
* 执行过此方法后,FinalBitmap的缓存已经失效,建议通过FinalBitmap.create()获取新的实例
*
* @author fantouch
*/
public void onDestroy() {
closeCache();
}
<二> FinalBitmap在代码里面的运用:
public class TaskListAdapter extends BaseAdapter {
private FinalBitmap fb;
private Context context;
private List<TaskListBean.TasksBean> dataArray = new ArrayList<TaskListBean.TasksBean>();
public FinalBitmap bitmap;
//初始化加载中时显示的图片
public Bitmap loadingBitmap;
//初始化加载失败显示的图片
public Bitmap failBitmap;
public TaskListAdapter(Context context) {
this.context = context;
this.bitmap = FinalBitmap.create(context);
this.loadingBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.square_default_loadding_image);
this.failBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.square_default_loaderror_image);
}
public List<TaskListBean.TasksBean> getDataArray() {
if (dataArray == null) {
dataArray = new ArrayList<TaskListBean.TasksBean>();
}
return dataArray;
}
public void setDataArray(List<TaskListBean.TasksBean> dataArray) {
bitmap = FinalBitmap.create(context);
this.dataArray = dataArray;
notifyDataSetChanged();
}
@Override
public int getCount() {
LogUtils.i("taskList count is " + getDataArray().size());
return getDataArray().size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return getDataArray().get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.task_item, null);
}
convertView.setTag(position);
final TaskListBean.TasksBean tasksBean = (TaskListBean.TasksBean) getItem(position);
String imageUrl = tasksBean.getGoods_img();
ImageView iv = (ImageView) convertView.findViewById(R.id.img_task_pic);
ImageView img_task_kind = (ImageView) convertView.findViewById(R.id.img_task_kind);
TextView task_money = (TextView) convertView.findViewById(R.id.tv_task_money);
TextView task_enmoney = (TextView) convertView.findViewById(R.id.tv_task_enmoney);
TextView task_number = (TextView) convertView.findViewById(R.id.tv_task_number);
TextView task_comment = (TextView) convertView.findViewById(R.id.tv_task_comment);
LinearLayout lv_taskinfo = (LinearLayout) convertView.findViewById(R.id.lv_taskinfo);
int tasktype = tasksBean.getTask_type();
try {
//代码区
switch (tasktype) {
case 0:
img_task_kind.setImageResource(R.drawable.task_share_pic);
break;
case 1:
img_task_kind.setImageResource(R.drawable.task_yaoqing);
break;
case 2:
img_task_kind.setImageResource(R.drawable.task_watchgood);
break;
case 3:
img_task_kind.setImageResource(R.drawable.task_watchpic);
break;
case 4:
img_task_kind.setImageResource(R.drawable.task_share_pic);
break;
//红包
case 6:
img_task_kind.setImageResource(R.drawable.task_hongbao);
break;
//签到
case 7:
img_task_kind.setImageResource(R.drawable.task_sign);
break;
default:
img_task_kind.setImageDrawable(new ColorDrawable(Color.TRANSPARENT));
break;
}
} catch (Exception e) {
e.printStackTrace();
e.printStackTrace();
}
try {
task_money.setText(tasksBean.getRed_campbell());
task_enmoney.setText("金:" + tasksBean.getMargin_price());
task_number.setText("已领份数 " + tasksBean.getSell_share_bonus_number());
task_comment.setText("评论(" + tasksBean.getTask_comment_count() + ")");
task_comment.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LogUtils.e(String.valueOf(position));
}
});
bitmap.display(iv,imageUrl,loadingBitmap,failBitmap);
final View finalConvertView = convertView;
lv_taskinfo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LogUtils.e(String.valueOf(position));
Intent intent = new Intent(finalConvertView.getContext(), TaskDetailActivity.class);
intent.putExtra("good_id", tasksBean.getGoods_id());
finalConvertView.getContext().startActivity(intent);
}
});
} catch (Exception e) {
e.printStackTrace();
}
return convertView;
}
}