Android中用双缓存技术,加载网络图片

最近在学校参加一个比赛,写的一个Android应用,里面要加载大量的网络图片,可是用传统的方法图片一多就会造成程序出现内存溢出而崩溃.因为自己也在学习中,所以看了很多博客和视频,然后参照这些大神的写源码,自己写了一个加载网络图片工具类.
里面要用到一个经典的图片缓存库DiskLruCache 下载地址为:  DiskLruCache下载

下面是使用这个类实现的 双缓存网络图片加载

[java] view plain copy

  1. public class DiskLruCacheUtils {
  2. private static DiskLruCacheUtils diskLruCacheUtils;
  3. private DiskLruCache diskLruCache; //LRU 磁盘缓存
  4. private LruCache<String, Bitmap> lruCache; //LRU 内存缓存
  5. private Context context;
  6. public DiskLruCacheUtils() {
  7. }
  8. public static DiskLruCacheUtils getInstance() {
  9. if (diskLruCacheUtils == null) {
  10. diskLruCacheUtils = new DiskLruCacheUtils();
  11. }
  12. return diskLruCacheUtils;
  13. }
  14. public void open(Context context, String disk_cache_subdir, int disk_cache_size) {
  15. try {
  16. this.context = context;
  17. // 获取到可用内存的最大值,使用内存超出这个值会引起OutOfMemory异常。
  18. // LruCache通过构造函数传入缓存值,以KB为单位。
  19. int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
  20. // 使用最大可用内存值的1/8作为缓存的大小。
  21. int cacheSize = maxMemory / 8;
  22. lruCache = new LruCache<>(cacheSize);
  23. /**
  24. * open()方法接受四个参数:
  25. * 第一个参数: 指定缓存地址
  26. * 第二个参数: 指定当前引用程序的版本号
  27. * 第三个参数: 指定同一个key可以对应多少个缓存文件,基本都是传1
  28. * 第四个参数: 指定最多可以缓存的字节数. 通常是10MB
  29. */
  30. diskLruCache = DiskLruCache.open(getCacheDir(disk_cache_subdir), getAppVersion(), 1, disk_cache_size);
  31. } catch (IOException e) {
  32. e.printStackTrace();
  33. }
  34. }
  35. /**
  36. * 获取磁盘缓存
  37. * @param url
  38. * @return
  39. */
  40. public InputStream getDiskCache(String url) {
  41. String key = hashkeyForDisk(url);
  42. try {
  43. DiskLruCache.Snapshot snapshot = diskLruCache.get(key);
  44. if (snapshot != null) {
  45. return snapshot.getInputStream(0);
  46. }
  47. } catch (IOException e) {
  48. e.printStackTrace();
  49. }
  50. return null;
  51. }
  52. /**
  53. * 下载图片并缓存到内存和磁盘中
  54. * @param url
  55. * @param callBack
  56. */
  57. public void putCache(final String url, final CallBack callBack){
  58. new AsyncTask<String,Void,Bitmap>(){
  59. @Override
  60. protected Bitmap doInBackground(String... params) {
  61. String key = hashkeyForDisk(params[0]);
  62. //                System.out.println("Key = "+key);
  63. DiskLruCache.Editor editor = null;
  64. Bitmap bitmap = null;
  65. URL url = null;
  66. try {
  67. url = new URL(params[0]);
  68. HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  69. conn.setReadTimeout(30*1000);
  70. conn.setConnectTimeout(30*1000);
  71. ByteArrayOutputStream baos = null;
  72. if (conn.getResponseCode()==HttpURLConnection.HTTP_OK){
  73. BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
  74. baos = new ByteArrayOutputStream();
  75. byte[] bytes = new byte[1024];
  76. int len = -1;
  77. while ((len = bis.read(bytes)) != -1) {
  78. baos.write(bytes, 0, len);
  79. }
  80. bis.close();
  81. baos.close();
  82. conn.disconnect();
  83. }
  84. if (baos !=null){
  85. bitmap = decodeSampleadBitmapFromStream(baos.toByteArray(),300,300);
  86. //                        bitmap = BitmapFactory.decodeByteArray(baos.toByteArray(),0,baos.toByteArray().length);
  87. addBitmapToCache(params[0],bitmap); // 添加到内存缓存
  88. editor = diskLruCache.edit(key); // 加入磁盘缓存
  89. //                        System.out.println(url.getFile());
  90. //位图压缩后输出(参数1: 压缩格式, 参数2: 质量(100 表示不压缩,30 表示压缩70%),参数3: 输出流)
  91. bitmap.compress(Bitmap.CompressFormat.JPEG,30,editor.newOutputStream(0));
  92. editor.commit();//提交
  93. }
  94. } catch (Exception e) {
  95. try {
  96. editor.abort();//放弃写入
  97. } catch (IOException e1) {
  98. e1.printStackTrace();
  99. }
  100. e.printStackTrace();
  101. }
  102. return bitmap;
  103. }
  104. @Override
  105. protected void onPostExecute(Bitmap bitmap) {
  106. super.onPostExecute(bitmap);
  107. callBack.response(bitmap);
  108. }
  109. }.execute(url);
  110. }
  111. /**
  112. * 关闭磁盘缓存
  113. */
  114. public void close(){
  115. if (diskLruCache!=null&& !diskLruCache.isClosed()){
  116. try {
  117. diskLruCache.close();
  118. } catch (IOException e) {
  119. e.printStackTrace();
  120. }
  121. }
  122. }
  123. /**
  124. * 刷新磁盘缓存
  125. */
  126. public void flush(){
  127. if (diskLruCache!=null){
  128. try {
  129. diskLruCache.flush();
  130. } catch (IOException e) {
  131. e.printStackTrace();
  132. }
  133. }
  134. }
  135. /**
  136. * 回调接口
  137. * @param <T>
  138. */
  139. public interface  CallBack<T>{
  140. public void response(T entity);
  141. }
  142. /**
  143. * 位图重新采样
  144. *
  145. * @param reqWidth  自定义的宽高
  146. * @param reqHeight
  147. * @return
  148. */
  149. public static Bitmap decodeSampleadBitmapFromStream(byte[] bytes, int reqWidth, int reqHeight) {
  150. BitmapFactory.Options options = new BitmapFactory.Options();
  151. options.inJustDecodeBounds = true;//只解析边界,不加载到内存中
  152. BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
  153. options.inSampleSize = calculatInSampleSize(options, reqWidth, reqHeight);//设置采样比为计算出的采样比例
  154. options.inJustDecodeBounds = false;
  155. return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);//重新解析图片
  156. }
  157. //添加缓存的对象
  158. public  void addBitmapToCache(String url,Bitmap bitmap){
  159. String key = hashkeyForDisk(url);
  160. if (getBitmapFromMenCache(key)==null){
  161. lruCache.put(key,bitmap);
  162. }
  163. }
  164. //从缓存中获取对象
  165. public  Bitmap getBitmapFromMenCache(String url){
  166. String key = hashkeyForDisk(url);
  167. return  lruCache.get(key);
  168. }
  169. /**
  170. * 计算位图的采样比例大小
  171. *
  172. * @param options
  173. * @param reqWidth  需要的宽高
  174. * @param reqHeight
  175. * @return
  176. */
  177. private static int calculatInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
  178. //获取位图的原宽高
  179. final int w = options.outWidth;
  180. final int h = options.outHeight;
  181. int inSampleSize = 1;
  182. //如果原图的宽高比需要的图片宽高大
  183. if (w > reqWidth || h > reqHeight) {
  184. if (w > h) {
  185. inSampleSize = Math.round((float) h / (float) reqHeight);
  186. } else {
  187. inSampleSize = Math.round((float) w / (float) reqWidth);
  188. }
  189. }
  190. return inSampleSize;
  191. }
  192. /**
  193. * MD5加密计算
  194. *
  195. * @param key
  196. * @return
  197. */
  198. private String hashkeyForDisk(String key) {
  199. String cachekey;
  200. try {
  201. final MessageDigest mDigest = MessageDigest.getInstance("MD5");
  202. mDigest.update(key.getBytes());
  203. cachekey = bytesToHexString(mDigest.digest());
  204. } catch (NoSuchAlgorithmException e) {
  205. cachekey = String.valueOf(key.hashCode());
  206. }
  207. return cachekey;
  208. }
  209. private String bytesToHexString(byte[] bytes) {
  210. StringBuilder sb = new StringBuilder();
  211. for (int i = 0; i < bytes.length; i++) {
  212. String hex = Integer.toHexString(0xff & bytes[i]);
  213. if (hex.length() == 1) {
  214. sb.append(0);
  215. }
  216. sb.append(hex);
  217. }
  218. return sb.toString();
  219. }
  220. /**
  221. * 获取缓存的地址
  222. *
  223. * @param name
  224. * @return
  225. */
  226. private File getCacheDir(String name) {
  227. String cachePath = Environment.getExternalStorageState()
  228. == Environment.MEDIA_MOUNTED || !Environment.isExternalStorageRemovable() ?
  229. context.getExternalCacheDir().getPath() : context.getCacheDir().getPath();
  230. return new File(cachePath + File.separator + name);
  231. }
  232. /**
  233. * 获取App的版本号
  234. *
  235. * @return
  236. */
  237. private int getAppVersion() {
  238. try {
  239. return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode;
  240. } catch (PackageManager.NameNotFoundException e) {
  241. e.printStackTrace();
  242. }
  243. return 1;
  244. }
  245. }

decodeSampleadBitmapFromStream(byte[] bytes, int reqWidth, int reqHeight)这个函数的实现可以参照 郭大神的博客:Android高效加载大图、多图方案,有效避免程序OOM

自己也是小白,好多都是复制粘贴,嘿嘿 !  这里就不进行代码的分析了(其实好多我也不懂...),下面就自己上demo把:

现将上面的DiskLruCache,
在项目中创建一个libcore.io包,将这.jar文件复制进去,然后实现上边的代码(有点多哈!直接复制过去把!). 我这里直接创建了一个DiskLruCacheUtils类里面就是上面的代码! 还是截个图:↓↓↓↓

使用这个工具类的方法:

在你需要的使用这类的Activity 或fragment中,首先:

[java] view plain copy

  1. private DiskLruCacheUtils diskLruCacheUtils;//创建对象
  2. private static final String DISK_CACHE_SUBDIR = "temp"; //设置图片缓存的文件
  3. private static final int DISK_CACHE_SIZE= 100*1024*1024; // 设置SD卡缓存的大小

然后在他们的声明周期中:

[html] view plain copy

  1. @Override
  2. protected void onResume() {
  3. super.onResume();
  4. diskLruCacheUtils = DiskLruCacheUtils.getInstance();
  5. diskLruCacheUtils.open(this,DISK_CACHE_SUBDIR,DISK_CACHE_SIZE);//打开缓存
  6. }
  7. @Override
  8. protected void onPause() {
  9. super.onPause();
  10. diskLruCacheUtils.flush(); //刷新缓存
  11. }
  12. @Override
  13. protected void onStop() {
  14. super.onStop();
  15. diskLruCacheUtils.close(); //关闭缓存
  16. }

加了这代码就可以真正的使用这个工具类了.
但是这样还不行,还得写个图片加载方法:

[html] view plain copy

  1. private void loadBitmap(String url, final ImageView imageView) {
  2. if (imageView.getTag().equals(url)) {
  3. //从内存缓存中取图片
  4. Bitmap bitmap = diskLruCacheUtils.getBitmapFromMenCache(url);
  5. if (bitmap == null) {
  6. //如果内存中为空 从磁盘缓存中取
  7. InputStream in = diskLruCacheUtils.getDiskCache(url);
  8. if (in == null) {
  9. //如果缓存中都为空,就通过网络加载,并加入缓存
  10. diskLruCacheUtils.putCache(url, new DiskLruCacheUtils.CallBack<Bitmap>() {
  11. @Override
  12. public void response(Bitmap entity) {
  13. //                            System.out.println("网络中下载...");
  14. imageView.setImageBitmap(entity);
  15. }
  16. });
  17. } else {
  18. System.out.println("磁盘中取出...");
  19. bitmap = BitmapFactory.decodeStream(in);
  20. diskLruCacheUtils.addBitmapToCache(url, bitmap);
  21. imageView.setImageBitmap(bitmap);
  22. }
  23. } else {
  24. //                System.out.println("内存中取出...");
  25. imageView.setImageBitmap(bitmap);
  26. }
  27. }
  28. }

然后在你需要加载图片的地方使用该方法就OK, 看起复杂其实还挺简单的  ...(复制过去不就行了...)

直接上Demo:
这是activity_main.xml文件

下面上布局文件 挺简单的 RecyclerView+CardView:

[html] view plain copy

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:paddingBottom="@dimen/activity_vertical_margin"
  7. android:paddingLeft="@dimen/activity_horizontal_margin"
  8. android:paddingRight="@dimen/activity_horizontal_margin"
  9. android:paddingTop="@dimen/activity_vertical_margin"
  10. tools:context="zhengliang.com.bitmaplrucache.MainActivity">
  11. <android.support.v7.widget.RecyclerView
  12. android:layout_width="match_parent"
  13. android:layout_height="match_parent"
  14. android:id="@+id/rlv_list"
  15. >
  16. </android.support.v7.widget.RecyclerView>
  17. </RelativeLayout>

挺简单的就一个 RecyclerView 因为要加载很多图片所以就用这个了,(哈哈! 我喜欢他的瀑布流! 爽到爆炸啊...)

这是item.xml文件

[html] view plain copy

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. android:layout_width="wrap_content"
  5. android:layout_height="wrap_content"
  6. android:layout_margin="2dp"
  7. app:cardBackgroundColor="@color/colorAccent"
  8. app:cardCornerRadius="2dp"
  9. android:background="@color/colorAccent"
  10. >
  11. <ImageView
  12. android:id="@+id/pic"
  13. android:layout_width="match_parent"
  14. android:layout_height="wrap_content"
  15. android:scaleType="centerCrop"
  16. />
  17. </android.support.v7.widget.CardView>

就一个CardView ,里面放了一个ImageView

MainActivity类中代码如下:
     
因为这里没有图片资源所以自己用Volley框架写了一个获取图片资源的getImageUrl()方法里面返回一些图片资源的URL地址 
(找图片真的很恼火啊,一条一条的把图片地址复制过来不是我的风范啊! 就在百度图片中经过千辛万苦扒了个图片API接口下来,哈哈 有图片咯!)

[java] view plain copy

  1. <pre name="code" class="java">public class MainActivity extends AppCompatActivity{
  2. private List<String> data;
  3. private DiskLruCacheUtils diskLruCacheUtils;
  4. private static final String DISK_CACHE_SUBDIR = "temp";
  5. private static final int DISK_CACHE_SIZE= 100*1024*1024;
  6. private RecyclerView rlvlist;
  7. private MyAdapter myAdapter;
  8. @Override
  9. protected void onCreate(Bundle savedInstanceState) {
  10. super.onCreate(savedInstanceState);
  11. setContentView(R.layout.activity_main);
  12. initViews();
  13. getImageUrl("http://image.baidu.com/channel/listjson?pn=0&rn=200&tag1=美女&tag2=小清新&ie=utf8");
  14. }
  15. private void initViews() {
  16. data = new ArrayList<String>();
  17. this.rlvlist = (RecyclerView) findViewById(R.id.rlv_list);
  18. rlvlist.setLayoutManager(new StaggeredGridLayoutManager(4,StaggeredGridLayoutManager.VERTICAL));
  19. }
  20. @Override
  21. protected void onResume() {
  22. super.onResume();
  23. diskLruCacheUtils = DiskLruCacheUtils.getInstance();
  24. diskLruCacheUtils.open(this,DISK_CACHE_SUBDIR,DISK_CACHE_SIZE);
  25. }
  26. @Override
  27. protected void onPause() {
  28. super.onPause();
  29. diskLruCacheUtils.flush();
  30. }
  31. @Override
  32. protected void onStop() {
  33. super.onStop();
  34. diskLruCacheUtils.close();
  35. }
  36. public void getImageUrl(String url){
  37. final RequestQueue mQueue = Volley.newRequestQueue(this);
  38. JsonObjectRequest stringRequest = new JsonObjectRequest(url, null,
  39. new Response.Listener<JSONObject>() {
  40. @Override
  41. public void onResponse(JSONObject jsonObject) {
  42. //                        System.out.println(jsonObject);
  43. try {
  44. JSONArray jsonArray = jsonObject.getJSONArray("data");
  45. for (int i = 0; i <jsonArray.length() ; i++) {
  46. JSONObject item = jsonArray.getJSONObject(i);
  47. String url = item.getString("image_url");
  48. String name = item.getString("tags");
  49. data.add(url);
  50. myAdapter = new MyAdapter(data,MainActivity.this,diskLruCacheUtils);
  51. rlvlist.setAdapter(myAdapter);
  52. myAdapter.notifyDataSetChanged();
  53. }
  54. } catch (JSONException e) {
  55. e.printStackTrace();
  56. }
  57. }
  58. }, new Response.ErrorListener() {
  59. @Override
  60. public void onErrorResponse(VolleyError volleyError) {
  61. }
  62. }
  63. );
  64. mQueue.add(stringRequest);
  65. if (data.size()==200){
  66. getImageUrl("http://image.baidu.com/channel/listjson?pn=0&rn=200&tag1=美女&tag2=全部&ie=utf8");
  67. }
  68. }
  69. public void getImageUrl2(String url){
  70. final RequestQueue mQueue = Volley.newRequestQueue(this);
  71. JsonObjectRequest stringRequest = new JsonObjectRequest(url, null,
  72. new Response.Listener<JSONObject>() {
  73. @Override
  74. public void onResponse(JSONObject jsonObject) {
  75. //                        System.out.println(jsonObject);
  76. try {
  77. JSONArray jsonArray = jsonObject.getJSONArray("imgs");
  78. for (int i = 0; i <jsonArray.length() ; i++) {
  79. JSONObject item = jsonArray.getJSONObject(i);
  80. String url = item.getString("hoverURL");
  81. String name = item.getString("fromPageTitle");
  82. data.add(url);
  83. myAdapter = new MyAdapter(data,MainActivity.this,diskLruCacheUtils);
  84. rlvlist.setAdapter(myAdapter);
  85. myAdapter.notifyDataSetChanged();
  86. }
  87. } catch (JSONException e) {
  88. e.printStackTrace();
  89. }
  90. }
  91. }, new Response.ErrorListener() {
  92. @Override
  93. public void onErrorResponse(VolleyError volleyError) {
  94. }
  95. }
  96. );
  97. mQueue.add(stringRequest);
  98. }
  99. }

然后是就是实现RecyclerView 的Adapter,因为网络图片的加载都要在Adapter中,所以loadBitmap()方法我就直接写在这里了  废话少说直接上代码

[java] view plain copy

  1. public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
  2. private List<String> list;
  3. private Context context;
  4. private DiskLruCacheUtils diskLruCacheUtils;
  5. public MyAdapter(List<String> list, Context context, DiskLruCacheUtils diskLruCacheUtils) {
  6. this.list = list;
  7. this.context = context;
  8. this.diskLruCacheUtils = diskLruCacheUtils;
  9. }
  10. @Override
  11. public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  12. View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_view,parent,false);
  13. return new ViewHolder(view);
  14. }
  15. @Override
  16. public void onBindViewHolder(ViewHolder holder, int position) {
  17. holder.pic.setTag(list.get(position));
  18. loadBitmap(list.get(position),holder.pic);
  19. System.out.println(position);
  20. }
  21. @Override
  22. public int getItemCount() {
  23. return list==null?0:list.size();
  24. }
  25. public static class ViewHolder extends RecyclerView.ViewHolder {
  26. public ImageView pic;
  27. public ViewHolder(View itemView) {
  28. super(itemView);
  29. pic = (ImageView) itemView.findViewById(R.id.pic);
  30. }
  31. }
  32. private void loadBitmap(String url, final ImageView imageView) {
  33. if (imageView.getTag().equals(url)) {
  34. //从内存缓存中取图片
  35. Bitmap bitmap = diskLruCacheUtils.getBitmapFromMenCache(url);
  36. if (bitmap == null) {
  37. //如果内存中为空 从磁盘缓存中取
  38. InputStream in = diskLruCacheUtils.getDiskCache(url);
  39. if (in == null) {
  40. //如果缓存中都为空,就通过网络加载,并加入缓存
  41. diskLruCacheUtils.putCache(url, new DiskLruCacheUtils.CallBack<Bitmap>() {
  42. @Override
  43. public void response(Bitmap entity) {
  44. //                            System.out.println("网络中下载...");
  45. imageView.setImageBitmap(entity);
  46. }
  47. });
  48. } else {
  49. System.out.println("磁盘中取出...");
  50. bitmap = BitmapFactory.decodeStream(in);
  51. diskLruCacheUtils.addBitmapToCache(url, bitmap);
  52. imageView.setImageBitmap(bitmap);
  53. }
  54. } else {
  55. //                System.out.println("内存中取出...");
  56. imageView.setImageBitmap(bitmap);
  57. }
  58. }
  59. }
  60. }

大工告成 看看效果

第一进入时全是从 显示"网络中下载..."  因为RecyclerView和ListView一样,超出屏幕的Item都会被回收,当再次滑动回到上次的位置就会重新获取item,并且会重新获取图片,.
   下面看看滑动回去打印的log

全是显示从内存中取出,并没有再重网络中下载,说明刚才的图片都缓存到内存中了,这样就加快的图片的显示,还节省了流量!(这年头流量伤不起啊!)
下面再看看关闭应用再打开是什么效果吧!

全部显示的是从磁盘中取出... 因为关闭应用,这个时候内存中缓存的图片就会被清空. 这个时候就会自动看SD中是否有缓存了. 并且从SD中取出的图片会再一次缓存到内存中去...我这里是加载的200张图片,完全没有问题,嘿嘿...

时间: 2024-08-02 07:00:24

Android中用双缓存技术,加载网络图片的相关文章

Android图片管理组件(双缓存+异步加载)

转自:http://www.oschina.net/code/snippet_219356_18887?p=3#comments ImageManager2这个类具有异步从网络下载图片,从sd读取本地图片,内存缓存,硬盘缓存,图片使用动画渐现等功能,已经将其应用在包含大量图片的应用中一年多,没有出现oom Android程序常常会内存溢出,网上也有很多解决方案,如软引用,手动调用recycle等等.但经过我们实践发现这些方案,都没能起到很好的效果,我们的应用依然会出现很多oom,尤其我们的应用包

Android三种基本的加载网络图片方式(转)

Android三种基本的加载网络图片方式,包括普通加载网络方式.用ImageLoader加载图片.用Volley加载图片. 1. [代码]普通加载网络方式 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

【Android基础】AsyncTask示例——加载网络图片

网络操作是一个严重的耗时操作,所以从Android 4.0版本开始,网络操作就被严禁放在主线程中,所以网络操作只能放在异步任务中. 下面是一个从网络上下载图片的示例,示例分为两个部分: - 异步处理下载图片 - UI线程中处理图片 下载的图片是在百度图片里面随便找的:http://img1.ph.126.net/GPS04o8gJYuG4ZOwlx6UQA==/978125544087835399.jpg 首先是Layout布局,这个比较简单,只需要一个ImageView显示图片和一个progr

[android]完美的解决方案ListView加载网络图片反弹问题

为什么 先说为什么有照片反弹. 使用convertView对ListView的每一个item优化,item的复用能够有效减少内存的占用.使ListView滑动更为流畅. 但会带来一个问题,当最顶部的item滑出屏幕时.会变成下一个从底部将要滑进来的item.每次滑进来的item都要去请求网络获得图片. 第一个item滑出去时,是带着图片的. 其ImageView指向了一块内存.当其慢慢滑出,从底部慢慢滑进时,底部的item与顶部(仅仅有一半在屏幕里能看到了)的还是指向 同一块内存.载入的了同一张

利用LruCache和DiskLruCache加载网络图片实现图片瀑布流效果(升级版)

MainActivity如下: package cc.patience7; import android.os.Bundle; import android.app.Activity; /** * Demo描述: * 采用瀑布流的形式加载大量网络图片 * 详细分析参见WaterfallScrollView * * 更新说明: * 在原本的的基础上添加了本地缓存DiskLruCache * * 所以在该示例中对于图片的缓存采用了:LruCache + DiskLruCache 的技术 * * 参考

利用LruCache加载网络图片实现图片瀑布流效果(改进版)

MainActivity如下: package cc.patience4; import cc.patience4.R; import android.os.Bundle; import android.app.Activity; /** * Demo描述: * 采用瀑布流的形式加载大量网络图片 * 详细分析参见WaterfallScrollView * * 更新说明: * 该示例在基础版的基础上加入了图片查看功能. * 点击瀑布流中一张图片后可欣赏图片并能对图片进行单指拖动和两指缩放. * 对

利用LruCache加载网络图片实现图片瀑布流效果(基础版)

MainActivity如下: package cc.patience3; import android.os.Bundle; import android.app.Activity; /** * Demo描述: * 采用瀑布流的形式加载大量网络图片 * 详细分析参见WaterfallScrollView * * 参考资料: * 1 http://blog.csdn.net/guolin_blog/article/details/10470797 * 2 http://blog.csdn.net

Android之ListView异步加载网络图片(优化缓存机制)【转】

网上关于这个方面的文章也不少,基本的思路是线程+缓存来解决.下面提出一些优化: 1.采用线程池 2.内存缓存+文件缓存 3.内存缓存中网上很多是采用SoftReference来防止堆溢出,这儿严格限制只能使用最大JVM内存的1/4 4.对下载的图片进行按比例缩放,以减少内存的消耗 具体的代码里面说明.先放上内存缓存类的代码MemoryCache.java: public class MemoryCache { private static final String TAG = "MemoryCa

Android 异步加载网络图片并缓存到本地

在android应用开发的时候,加载网络图片是一个非常重要的部分,很多图片不可能放在本地,所以就必须要从服务器或者网络读取图片. 软引用是一个现在非常流行的方法,用户体验比较好,不用每次都需要从网络下载图片,如果下载后就存到本地,下次读取时首先查看本地有没有,如果没有再从网络读取. 记得2月份在和爱奇艺公司的项目总监一起搞联通的OTT盒子的时候他就提了一下软引用,奇艺做的手机客户端就是采用这种方法,所以你会发现奇艺客户端占用很大的空间,下面就分享一下异步加载网络图片的方法吧. FileCache