1.回顾
上篇学习了,gridview 加载数据;图片请求,LruCache 缓存实现;
上篇遗留问题:
(1)优化列表数据加载:当滑动到列表哪里,加载这里的图片;
(2)LruCache 缓存 实现 sizeof 方法;(一定要实现)
2.重点
(1)LruCahce 缓存 修复
(2)优化列表数据加载:AsyncTask 异步加载图片
(3)圆角图片实现
3. 效果和对比
背景:
(1)没有LruCahce 缓存实现:当在滑动的时候,一直在请求图片,这是不可取的,因为消耗流量太厉害;
(2)有LruCache缓存,没有优化的时候:当在滑动的时候,图片会加载到GridView中,当图片量很大的时候,会通通加载到缓存中;还有就是,在滑动过程中,如果边滑动,边加载,gridview可能发生卡顿现象;
(3)LruCache缓存和优化列表实现 :缓存就不说了,这是必须的;数据加载优化,当滑动的时候,停止任务加载;当停止滑动的时候,进行图片数据加载;也就是说,停止滑动的时候,加载任务就当前页面中的几张图片加载任务;
(4)效果图
4.LruCache 优化实现
在使用LrcCache的时候,必须实现 sizeOf 方法,来计算大小;
package com.example.Adapter;
import java.util.ArrayList;
import java.util.List;
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
public class ImageCache {
/**
* 缓存类 LruCache
*/
private static LruCache<String,Bitmap> imgCache;
/**
* 实例
*/
private static ImageCache instance;
/**
* 判断key 是否存在
*/
private static List<String> lruKeys;
public ImageCache() {
// 初始化 ,拿可用 内存的8分之一
int maxMemory=(int) Runtime.getRuntime().maxMemory();
int cacheMemory=maxMemory/8;
imgCache=new LruCache<String, Bitmap>(cacheMemory){
@Override
protected int sizeOf(String key, Bitmap value) {
// 必须重写此方法,计算bitmap的大小
return value.getRowBytes()*value.getHeight();
}
};
lruKeys=new ArrayList<String>();
}
/**
* 单例模式 创建 ImageCache 缓存类
* @return
*/
public static ImageCache getinstance(){
if(instance==null){
instance=new ImageCache();
return instance;
}else{
return instance;
}
}
/**
* 添加缓存
* @param key
* @param bitmap
*/
public void setCache(String key,Bitmap bitmap){
imgCache.put(key, bitmap);
lruKeys.add(key);
}
/**
* 得到缓存
* @param key
* @return
*/
public Bitmap getCache(String key){
return imgCache.get(key);
}
/**
* 判断是否存在key
* @param key
* @return
*/
public boolean isKey(String key){
return lruKeys.contains(key);
}
}
5.Adapter实现
(1)实现 OnScrollListener 接口;
(2)在Adapter里进行setTag操作;
(3)通过AsyncTask实现异步加载图片:优点 加载任务的可控性;
package com.example.Adapter;
import java.util.List;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.TextView;
import com.example.asynctask.R;
public class GridAdapter extends BaseAdapter implements OnScrollListener {
private List<MoviesIfo> movies;
private Context context;
private ViewHolder holder;
// 存放全部的URL
public static String[] urls;
private RequestImageByAsyncTask asyncReqImage;
public GridAdapter(List<MoviesIfo> movies, Context context,GridView gridView) {
// 数据
this.movies = movies;
this.context = context;
//第二步:初始化
asyncReqImage=new RequestImageByAsyncTask(gridView);
this.urls = new String[movies.size()];
for (int i = 0; i < urls.length; i++) {
urls[i] = movies.get(i).getPic();
}
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return movies.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return movies.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@SuppressLint("ViewHolder")
@Override
public View getView(int position, View convertView, ViewGroup parent) {
MoviesIfo ifo = movies.get(position);
// 加载 布局 并 设置 布局
holder = new ViewHolder();
convertView = View.inflate(context, R.layout.gridlist_item, null);
holder.list_image = (ImageView) convertView
.findViewById(R.id.list_image);
holder.list_tvname = (TextView) convertView
.findViewById(R.id.list_tvname);
holder.list_tvtotle = (TextView) convertView
.findViewById(R.id.list_tvtotle);
// 设置图片
holder.list_image.setScaleType(ScaleType.FIT_XY);
holder.list_image.setImageResource(R.drawable.tubiao);
holder.list_tvname.setText(ifo.getName());
holder.list_tvtotle.setText("给力的电影 id= " + ifo.getId());
/**
* 第一步:给图片设置Tag
*/
holder.list_image.setTag(urls[position]);
// ReqeustImageByThread reqeustImage = new
// ReqeustImageByThread(ifo.getPic(),
// holder.list_image);
// reqeustImage.start();
// RequestImageByRunnable requestImageByRunnable = new RequestImageByRunnable(
// ifo.getPic(), holder.list_image);
// requestImageByRunnable.RequestImage();
return convertView;
}
class ViewHolder {
public ImageView list_image;
public TextView list_tvname, list_tvtotle;
}
private int start;
private int end;
//第一次加载
private boolean isFrist=true;
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// 状态改变
// 停止滑动的时候
if (SCROLL_STATE_IDLE == scrollState) {
// 停止滑动 ,开始加载数据
// 如果在 滑动的时候加载数据,可能发生卡顿
asyncReqImage.ReqImage(start, end);
} else {
// 滑动时,取消加载
asyncReqImage.Reqcancel();
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// 位置控制
start = firstVisibleItem;
end = firstVisibleItem + visibleItemCount;
/**
* 两个条件:
* isFrist: 判断第一次加载;
* visibleItemCount :可用item的数量 大于0 时 进行第一次加载;
*/
if(isFrist&&visibleItemCount>0){
asyncReqImage.ReqImage(start, end);
isFrist=false;
}
}
}
6.异步加载
(1)将异步任务 存放在list中,实现任务的可控性;
(2)圆角实现:直接将bitmap 转换为圆角 存放在缓存中;
package com.example.Adapter;
import java.util.ArrayList;
import java.util.List;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.widget.GridView;
import android.widget.ImageView;
import com.example.Http.PictureDraw;
import com.example.Http.UrlConnGetdata;
import com.example.asynctask.R;
public class RequestImageByAsyncTask {
/**
* AsyncTask 实现异步加载
*
*/
private GridView gridView;
/**
* 初始化 基础地址
*/
private final static String baseUrl = "http://192.168.75.1:8081/GoodsServers/";
/**
* 存放 所有的异步任务:当滑动的时候,停止加载;当停止滑动的时候,加载数据;为了避免卡顿
*/
private List<ReqImageAsyncTask> asyncTasks = new ArrayList<RequestImageByAsyncTask.ReqImageAsyncTask>();
/**
* GridView 初始化
*
* @param gridView
*/
public RequestImageByAsyncTask(GridView gridView) {
// 初始化 listview :作用 通过 listview 来 获取 ImageView的值
this.gridView = gridView;
}
/**
* 添加加载任务
*
* @param start
* @param end
*/
public void ReqImage(int start, int end) {
for (int i = start; i < end; i++) {
String url = GridAdapter.urls[i];
ImageView imageView = (ImageView) gridView.findViewWithTag(url);
ReqImageAsyncTask asyncTask = new ReqImageAsyncTask(imageView);
asyncTask.execute(baseUrl + url);
asyncTasks.add(asyncTask);
}
}
/**
* 取消请求任务
*
*/
public void Reqcancel() {
for (ReqImageAsyncTask reqImageAsyncTask : asyncTasks) {
if (!reqImageAsyncTask.isCancelled()) {
reqImageAsyncTask.cancel(true);
}
}
}
/**
* 根据路径 获得图片
*
* @param picpath
* @return
*/
private Bitmap getBitmap(String picpath) {
return UrlConnGetdata.getBitmap(picpath);
}
/**
* 请求图片 异步任务
*
* @author yuan
*
*/
class ReqImageAsyncTask extends AsyncTask<String, Void, Bitmap> {
private ImageView Img;
public ReqImageAsyncTask(ImageView view) {
// 初始化
this.Img = view;
}
@Override
protected Bitmap doInBackground(String... params) {
// 请求图片
String ReqUrl = params[0];
Bitmap bitmap = null;
ImageCache imageCache = ImageCache.getinstance();
if (imageCache.isKey(ReqUrl)) {
// 如果 存在 ,去内存中的
bitmap = imageCache.getCache(ReqUrl);
} else {
// 否则 ,请求 图片
bitmap = getBitmap(ReqUrl);
//存到缓存中 ,圆角
imageCache.setCache(ReqUrl,
PictureDraw.toRoundCorner(bitmap, 10));
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
// 得到图片
if (bitmap != null) {
Img.setImageBitmap(bitmap);
} else {
Img.setImageResource(R.drawable.fail);
}
}
}
}
7.圆角实现
/** */
/**
* 把图片变成圆角
*
* @param bitmap
* 需要修改的图片
* @param pixels
* 圆角的弧度
* @return 圆角图片
*/
public static Bitmap toRoundCorner(Bitmap bitmap, int pixels) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = pixels;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
8.总结
在进行列表优化的时候,主要通过 onScroll() 和 onScrollStateChanged() 两个方法来判断,当前页的数据;
还有获得ImageView 通过 findviewWithTag实现;与之前设置的tag对应;