Android 多线程 异步加载
Android 应用中需要显示网络图片时,图片的加载过程较为耗时,因此加载过程使用线程池进行管理,
同时使用本地缓存保存图片(当来回滚动ListView时,调用缓存的图片),这样加载和显示图片较为友好。
参考:http://www.eoeandroid.com/thread-210082-1-1.html?_dsign=1b202888
核心代码:
1. MainActivity
package com.desmand.threadtest; import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView; import java.io.IOException;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class MainActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); loadImage("http://www.baidu.com/img/baidu_logo.gif", R.id.imageView1, 1);
loadImage("http://cn.bing.com/sa/simg/bing_p_rr_teal.ico", R.id.imageView2, 2);
loadImage("http://cache.soso.com/30d/img/web/logo.gif", R.id.imageView3, 3);
loadImage("http://csdnimg.cn/www/images/csdnindex_logo.gif", R.id.imageView4, 4);
loadImage("http://images.cnblogs.com/logo_small.gif", R.id.imageView5, 5);
} // 4. 引入线程池,并引入内存缓存功能,并对外部调用封装了接口,简化调用过程
private AsyncImageLoader asyncImageLoader = new AsyncImageLoader(); private void loadImage(String url, final int id, final int count){ // 如果缓存过就会从缓存中取出图像,ImageCallback接口中方法也不会被执行
Drawable cacheImage = asyncImageLoader.loadDrawable(url, new AsyncImageLoader.ImageCallback() { // 请参见实现:如果第一次加载url时下面方法会执行
@Override
public void imageLoaded(Drawable imageDrawable) {
((ImageView) findViewById(id)).setImageDrawable(imageDrawable);
Log.i("test", "1count: " + count);
}
}); if (cacheImage != null){
((ImageView) findViewById(id)).setImageDrawable(cacheImage);
Log.i("test", "2count: " + count);
}
} // 3. 引入线程池来管理多线程
// private Handler handler3 = new Handler();
// private ExecutorService executorService = Executors.newFixedThreadPool(5);
//
// private void loadImage(final String url, final int id, final int count) {
// executorService.submit(new Runnable() {
// @Override
// public void run() {
// final Drawable drawable;
// try {
// drawable = Drawable.createFromStream(new URL(url).openStream(), "image.png");
//
// //模拟网络延时
// SystemClock.sleep(2000);
// handler3.post(new Runnable() {
// @Override
// public void run() {
// ((ImageView) MainActivity.this.findViewById(id)).setImageDrawable(drawable);
// Log.i("test", "count: " + count);
// }
// });
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// });
// } // 2. 采用handler+Thread模式实现多线程异步加载
// final Handler handler2 = new Handler() {
// @Override
// public void handleMessage(Message msg) {
// ((ImageView) MainActivity.this.findViewById(msg.arg1)).setImageDrawable((Drawable) msg.obj);
// Log.i("test", "count: " + msg.arg2);
// }
// };
//
// private void loadImage(final String url, final int id, final int count) {
// Thread thread = new Thread() {
// @Override
// public void run() {
// Drawable drawable = null;
// try {
// drawable = Drawable.createFromStream(new URL(url).openStream(), "image.png");
// } catch (IOException e) {
// Log.d("test", e.getMessage());
// }
//
// // 模拟网络延时
// SystemClock.sleep(2000);
//
// Message message = handler2.obtainMessage();
// message.arg1 = id;
// message.obj = drawable;
// message.arg2 = count;
// handler2.sendMessage(message);
// }
// };
// thread.start();
// } // 1. 主线程直接加载,不可用
// private Handler handler = new Handler();
// private void loadImage(final String url, final int id, final int count) {
// handler.post(new Runnable() {
// public void run() {
// Drawable drawable = null;
// try {
// drawable = Drawable.createFromStream(new URL(url).openStream(), "image.gif");
// } catch (IOException e) {
// Log.d("test", e.getMessage());
// }
//
// if (drawable == null) {
// Log.d("test", "null drawable");
// } else {
// Log.d("test", "not null drawable");
// }
//
// // 为了测试缓存而模拟的网络延时
// SystemClock.sleep(2000);
//
// ((ImageView) MainActivity.this.findViewById(id)).setImageDrawable(drawable);
// }
// });
// } }
2. AsyncImageLoader
package com.desmand.threadtest; import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.SystemClock; import java.io.IOException;
import java.lang.ref.SoftReference;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; /**
* Created by fansen on 2016/02/23.
*/
public class AsyncImageLoader {
// 为了加快速度,在内存中开启缓存(主要应用于重复图片较多时,或者同一个图片要多次被访问,比如在ListView时来回滚动)
public Map<String, SoftReference<Drawable>> imageCache = new HashMap<>();
private ExecutorService executorService = Executors.newFixedThreadPool(5);
private Handler handler = new Handler(); /**
* @param imageUrl 图像url地址
* @param callback 回调接口
* @return 返回内存中缓存的图像,第一次加载返回null
*/
public Drawable loadDrawable(final String imageUrl, final ImageCallback callback) { // 如果缓存过就从缓存中取出数据
if (imageCache.containsKey(imageUrl)) {
SoftReference<Drawable> softReference = imageCache.get(imageUrl);
if (softReference.get() != null) {
return softReference.get();
}
} // 缓存中没有图像,则从网络上取出数据,并将取出的数据缓存到内存中
executorService.submit(new Runnable() {
@Override
public void run() {
final Drawable drawable = loadImageFromUrl(imageUrl);
imageCache.put(imageUrl, new SoftReference<>(drawable)); handler.post(new Runnable() {
@Override
public void run() {
callback.imageLoaded(drawable);
}
});
}
}); return null;
} // 从网络上取数据方法
protected Drawable loadImageFromUrl(String imageUrl) {
try {
// 测试时,模拟网络延时,实际时这行代码不能有
SystemClock.sleep(2000);
return Drawable.createFromStream(new URL(imageUrl).openStream(), "image.png");
} catch (IOException e) {
e.printStackTrace();
}
return null;
} //对外界开放的回调接口
public interface ImageCallback {
//注意 此方法是用来设置目标对象的图像资源
void imageLoaded(Drawable imageDrawable); } }
Android 多线程 异步加载的更多相关文章
- Android图片异步加载之Android-Universal-Image-Loader
将近一个月没有更新博客了,由于这段时间以来准备毕业论文等各种事务缠身,一直没有时间和精力沉下来继续学习和整理一些东西.最近刚刚恢复到正轨,正好这两天看了下Android上关于图片异步加载的开源项目,就 ...
- Android图片异步加载之Android-Universal-Image-Loader(转)
今天要介绍的是Github上一个使用非常广泛的图片异步加载库Android-Universal-Image-Loader,该项目的功能十分强大,可以说是我见过的目前功能最全.性能最优的图片异步加载解决 ...
- Android 图片异步加载的体会,SoftReference已经不再适用
在网络上搜索Android图片异步加载的相关文章,目前大部分提到的解决方案,都是采用Map<String, SoftReference<Drawable>> 这样软引用的 ...
- C# 多线程 异步加载 窗体
C# 多线程 异步加载 窗体 分类: C#2014-05-28 16:57 1286人阅读 评论(0) 收藏 举报 异步加载 我们在使用 windowform 编程的时候,我们或许可能会越到,各种在窗 ...
- [Android] Android 用于异步加载 ContentProvider 中的内容的机制 -- Loader 机制 (LoaderManager + CursorLoader + LoaderManager.LoaderCallbacks)
Android 用于异步加载 ContentProvider 中的内容的机制 -- Loader 机制 (LoaderManager + CursorLoader + LoaderManager.Lo ...
- android 网络异步加载数据进度条
ProgressDialog progressDialog = null; public static final int MESSAGETYPE = 0; private void execute( ...
- Android开发--异步加载
因为移动端软件开发思维模式或者说是开发的架构其实是不分平台和编程语言的,就拿安卓和IOS来说,他们都是移动前端app开发展示数据和用户交互数据的数据终端,移动架构的几个大模块:UI界面展示.本地数据可 ...
- [置顶] Android图片异步加载之Android-Universal-Image-Loader
将近一个月没有更新博客了,由于这段时间以来准备毕业论文等各种事务缠身,一直没有时间和精力沉下来继续学习和整理一些东西.最近刚刚恢复到正轨,正好这两天看了下Android上关于图片异步加载的开源项目,就 ...
- Android图片异步加载框架Android-Universal-Image-Loader
版权声明:本文为博主原创文章,未经博主允许不得转载. Android-Universal-Image-Loader是一个图片异步加载,缓存和显示的框架.这个框架已经被很多开发者所使用,是最常用的几个 ...
随机推荐
- 【10】了解Bootstrap栅格系统基础案例(5)
这次我们来说下列排序: 通过使用 .col-md-push-* 和 .col-md-pull-* 类就可以很容易的改变列(column)的顺序. <!DOCTYPE html> <h ...
- BZOJ 2818GCD
Description 给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对. Input 一个整数N Output 如题 Sample Input 4 Sam ...
- <三> jQuery 选择器
jQuery 选择器选择需要应用效果的元素,jQuery 元素选择器和属性选择器允许您通过标签名.属性名或内容对 HTML 元素进行选择.选择器允许您对 HTML 元素组或单个元素进行操作. 元素选择 ...
- ios更改UITabBarController背景以及选中背景图片的方法
一.背景图片 1.5.0以上版本 UIImage *image = [UIImage imageNamed:@"system_tabbar_bg.png"]; [ ...
- hdu 1255 覆盖的面积 (线段树处理面积覆盖问题(模板))
http://acm.hdu.edu.cn/showproblem.php?pid=1255 覆盖的面积 Time Limit: 10000/5000 MS (Java/Others) Memo ...
- 一般处理程序(ashx)和页面处理程序(aspx)的区别
客官请看图 图中的Httphandler就是处理程序. 两者的共同点 如果把aspx处理程序和ashx处理程序放到上图中,他们是处在相同的位置的, 他们都实现了IHttphandler接口.实 ...
- Codeforces Round #360 div2
Problem_A(CodeForces 688A): 题意: 有d天, n个人.如果这n个人同时出现, 那么你就赢不了他们所有的人, 除此之外, 你可以赢他们所有到场的人. 到场人数为0也算赢. 现 ...
- [转载]C# 多选功能(checkedListBox控件)
// 全选; private void btn_allSelected_Click(object sender, EventArgs e) { //this.CheckedListBox1.Check ...
- zoj 3765
一道区间更新.查询的题: 但是线段树不能做插入: 后来才知道用splay: splay用来做区间查询的话,先将l-1旋转到根节点,然后把r+1旋转到根节点的右节点: 这样的话,根节点的右节点的左子树就 ...
- 想弄清楚LIBEVENT和EPOLL之类的关系,不要因为走得太急而迷失了方向
要一步一步构架起整个体系, 来日方长. 系统调用级别的EPOLL和函数库LIBEVENT之间,大体关系应该是如何呢? 网上有说法: ~~~~~~~~~~~~~~ libevent对底层多路复用机制的封 ...