网络图片异步加载(用到多线程(线程池),java回调机制,图片缓存,图片的动画)

来源:互联网 发布:剑三捏脸数据排名 编辑:程序博客网 时间:2024/06/05 17:27

用线程池,回调,进行图片的异步加载,实现图片的缓存,并且以渐隐动画的方式显示出来

不必多说,线程池,回调,这些在java里面都算是非常重要的角色。

线程池线程池就是管理多线程的一个东西,在多线程的操作中,如果遇到大量需要很多线程进行执行任务的时候,有的时候真正在线程里面执行任务的时间都不一定有进行线程的开启和销毁需要的时间多,这个时候使用线程池,就大大提高了处理器的吞吐能力,自然就提高了程序的性能。
       而在这里只是用到了这些东西,线程池不多说,说起来说不完,东西太多,以后有可能回再出一篇关于线程池的理解的帖子

回调简单来说,回调就是是一种常见的设计模型,他把工作流内的某个功能,按照约定的接口暴露给外部使用者,为外部使用者提供数据,或要求外部使用者提供数据
 比如说A为一个activity,S为一个service,A请求S下载一个mp3文件,然后下载后A想打开,但是没有下载完打开肯定会出错,而A不能一直等着mp3一点点的下载,所以在A给S发送这个指令后,S开始下载,A去干其他的事情,当S下载完成后直接回调给A一个消息,A这下就知道mp3下载完成了,这个时候就可以直接打开。就是这个简单的道理,这里也不做过多的解释,之后会继续做出一边文章详解。

先来一张效果图,截图不是很好,意思到了:


这里直接上代码:

一共有3个类:
1.MainActivity.java进行图片的展示界面
2.AsyncLoad.java 进行图片的异步加载
3.SetImage.java 进行回调接口的实现,并且加入动画
名字起的比较随便··

代码注释比较详细,就不多于赘述
1.MainActivity.java
<pre name="code" class="java">public class MainActivity extends Activity {private String[] list = {"http://10.10.8.115:8080/HealthyData/images/8a94622d62965b95104cb8558ccabad8.jpg","http://10.10.8.115:8080/HealthyData/images/191cd461a9120bb37b1f88dd3019613b.jpg","http://10.10.8.115:8080/HealthyData/images/f6c26210fbfa76e958602264d5b0e016.jpg","http://10.10.8.115:8080/HealthyData/images/a7f36e53bf308290a97c478afb446221.jpg","http://10.10.8.115:8080/HealthyData/images/d4919ff7ca954a681193d8c2f696c564.jpg","http://10.10.8.115:8080/HealthyData/images/b2901d3d40e2343210e32c2a17a24d4b.jpg","http://10.10.8.115:8080/HealthyData/images/cbbe89dd3419dad0f6c484186f34c9a7.jpg","http://10.10.8.115:8080/HealthyData/images/0faa3c63a1c1c4040ccb0b59ff2fdfde.jpg","http://10.10.8.115:8080/HealthyData/images/7dca92b74a9b83ce021cfdc5fd29fc07.jpg","http://10.10.8.115:8080/HealthyData/images/3cef2859c059905002eae29915be5be7.jpg","http://10.10.8.115:8080/HealthyData/images/4f0952f7456ff2e545d5bee4eef0be3b.jpg","http://10.10.8.115:8080/HealthyData/images/e0e14234a862c5eb24750ec71cbf0320.jpg","http://10.10.8.115:8080/HealthyData/images/03ac23dd101dd18f107aae2d095b66d4.jpg","http://10.10.8.115:8080/HealthyData/images/9053a81db4b4d5e9e00869df3897b75a.jpg","http://10.10.8.115:8080/HealthyData/images/02829476989b75950dc58935ec2cf132.jpg","http://10.10.8.115:8080/HealthyData/images/44d3d2eb56068a29dd4d2e47d1f863f0.jpg","http://10.10.8.115:8080/HealthyData/images/1114565897b785a688c5e48dbbf41970.jpg","http://10.10.8.115:8080/HealthyData/images/1a5687efb11ccb74e5e0e36cb95564e9.jpg","http://10.10.8.115:8080/HealthyData/images/ecbc3b076f9ff3c12d1e9553a4bc3c64.jpg","http://10.10.8.115:8080/HealthyData/msjimages/image_basic/msj_b282bc0649dabe89fe40230d1b89cd0e_150x150.jpg","http://10.10.8.115:8080/HealthyData/msjimages/image_basic/msj_ae66c41d0d5f6c179060c3dfbdbe7ad8_150x150.jpg","http://10.10.8.115:8080/HealthyData/msjimages/image_basic/msj_80a635542077dee4034ef36963bc294f_150x150.jpg","http://10.10.8.115:8080/HealthyData/msjimages/image_basic/msj_3ee3f63bbcdde088b1baaa862ac922c1_150x150.jpg","http://10.10.8.115:8080/HealthyData/msjimages/image_basic/msj_b7c42a1d52656b28fc99b2f327c40970_150x150.jpg","http://10.10.8.115:8080/HealthyData/msjimages/image_basic/msj_9e5fac83ff569458926c0f5d4743b84c_150x150.jpg","http://10.10.8.115:8080/HealthyData/msjimages/image_basic/msj_c5bfa8da120bcd1b31583d3bb178c7ac_150x150.jpg","http://10.10.8.115:8080/HealthyData/msjimages/image_basic/msj_4219856824eedba5fa00b67f6bc18ef7_150x150.jpg","http://10.10.8.115:8080/HealthyData/msjimages/image_basic/msj_a2fed0ed6a8da6348dde541b437cafa7_150x150.jpg","http://10.10.8.115:8080/HealthyData/msjimages/image_basic/msj_45b0841f5bca5b0a0d6bf7591acbe1e0_150x150.jpg","http://10.10.8.115:8080/HealthyData/msjimages/image_basic/msj_548d5c7b351efd7b2a62d435b3b36671_150x150.jpg",};private Button button;private GridView gridView;private ExecutorService pool;private Map<String, SoftReference<Bitmap>> iCache;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);pool = Executors.newFixedThreadPool(5);iCache = new HashMap<String, SoftReference<Bitmap>>();button = (Button) findViewById(R.id.button);gridView = (GridView) findViewById(R.id.grid);button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {gridView.setAdapter(new Adapters(list, getApplicationContext()));}});}class Adapters extends BaseAdapter {private String[] list;private Context context;public Adapters(String[] list, Context context) {this.list = list;this.context = context;}@Overridepublic int getCount() {return list.length;}@Overridepublic Object getItem(int position) {return list[position];}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {convertView = LayoutInflater.from(context).inflate(R.layout.adapter, null);ImageView imageView = (ImageView) convertView.findViewById(R.id.iv);// 实例化一个实现回调接口的对象,将该对象作为参数放到回调监听中SetImage setImage = new SetImage(imageView);// 实例化一个异步加载图片类的对象AsyncLoad asyncLoad = new AsyncLoad(pool, iCache);// 在这里设置回调监听asyncLoad.loadDrawable(list[position], setImage);return convertView;}}}

这里的list是我自己搭建服务器里面的图片文件,这个需要的朋友得自己去找一些可用的图片资源链接。

2.AsyncLoad.java 

//该类的主要作用是实现图片的异步加载public class AsyncLoad {// 图片缓存对象// 键是图片的URL,值是一个SoftReference对象,该对象指向一个Bitmap对象private Map<String, SoftReference<Bitmap>> imageCache;// 使用线程池去执行任务private ExecutorService pool;// 初始化线程池和缓存public AsyncLoad(ExecutorService pool,Map<String, SoftReference<Bitmap>> imageCache) {this.pool = pool;this.imageCache = imageCache;}// 实现图片的异步加载public void loadDrawable(final String imageUrl, final ImageCallback callback) {// 查询缓存,查看当前需要下载的图片是否已经存在于缓存当中if (imageCache.containsKey(imageUrl)) {SoftReference<Bitmap> softReference = imageCache.get(imageUrl);if (softReference.get() != null) {callback.imageLoaded(softReference.get());return;}}// 缓存中没有图片,就去下载final Handler handler = new Handler() {public void handleMessage(Message msg) {// 图片下载好以后在这里进行回调,就会直接去调用实现该接口的对象所实现的方法callback.imageLoaded((Bitmap) msg.obj);}};// 新建图片下载任务放到线程池里面去执行pool.execute(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName());Bitmap bitmap = loadImageFromUrl(imageUrl);// 得到图片后放到缓存之中imageCache.put(imageUrl, new SoftReference<Bitmap>(bitmap));Message message = handler.obtainMessage(0, bitmap);handler.sendMessage(message);}});}// 该方法用于根据图片的URL,从网络上下载图片protected Bitmap loadImageFromUrl(String imageUrl) {// 这里设置option是为了防止图片过大,造成内存溢出BitmapFactory.Options options = new Options();options.inJustDecodeBounds = true;try {BitmapFactory.decodeStream(new URL(imageUrl).openStream(),new Rect(), options);// 根据图片的宽进行放大倍数的计算int length = options.outWidth;double a = length / 100;if (a < 1) {a = 1;}options.inSampleSize = (int) (a + 1);options.inJustDecodeBounds = false;// 下载图片Bitmap bitmap = BitmapFactory.decodeStream(new URL(imageUrl).openStream(), new Rect(), options);return bitmap;} catch (MalformedURLException e1) {e1.printStackTrace();} catch (IOException e1) {e1.printStackTrace();}return null;// try {// // 根据图片的URL,下载图片,并生成一个Drawable对象// return Drawable.createFromStream(new URL(imageUrl).openStream(),// "src");// } catch (Exception e) {// throw new RuntimeException(e);// }}// 回调接口public interface ImageCallback {public void imageLoaded(Bitmap bitmap);}}

3.SetImage.java 

/** * 实现回调接口 *  * @author  * @version 1.0.0 * @2013-4-23 下午3:30:30 */public class SetImage implements AsyncLoad.ImageCallback {private ImageView iView;// 这里进行要放置图片的ImageView 的初始化public SetImage(ImageView imageView) {this.iView = imageView;}// 回调方法,当方法被调用的时候,直接进行图片的加载@Overridepublic void imageLoaded(Bitmap imageDrawable) {// 设置动画效果AnimationSet animationSet = new AnimationSet(true);AlphaAnimation alphaAnimation = new AlphaAnimation(0.1f, 1f);ScaleAnimation scaleAnimation = new ScaleAnimation(0f, 1f, 0f, 1f,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f);RotateAnimation rotateAnimation = new RotateAnimation(0, 360,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f);// 加入动画animationSet.setDuration(3 * 1000);animationSet.addAnimation(alphaAnimation);//设置渐隐animationSet.addAnimation(scaleAnimation);//设置伸缩// animationSet.addAnimation(rotateAnimation);//设置旋转//设置停留在动画最后的状态animationSet.setFillAfter(true);//为ImageView加载动画iView.startAnimation(animationSet);iView.setImageBitmap(imageDrawable);iView.setScaleType(ScaleType.FIT_XY);}}




源码地址