Android-GridView实例(优化列表数据加载,图片圆角,LruCache优化)

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对应;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值