Android异步加载全解析之引入一级缓存

| 收藏本文 下载本文 作者:TenderPinecone

这里给大家分享一些Android异步加载全解析之引入一级缓存(共含6篇),供大家参考。同时,但愿您也能像本文投稿人“TenderPinecone”一样,积极向本站投稿分享好文章。

Android异步加载全解析之引入一级缓存

篇1:Android异步加载全解析之引入一级缓存

通过对图像的缩放,我们做到了对大图的异步加载优化,但是现在的App不仅是高清大图,更是高清多图,动不动就是图文混排,以图代文,如果这些图片都加载到内存中,必定会OOM,因此,在用户浏览完图像后,应当立即将这些废弃的图像回收,但是,这又带来了另一个问题,也就是当用户在浏览完一次图片后,如果还要返回去再进行重新浏览,那么这些回收掉的图像又要重新进行加载,保不准就要那些无聊到 的人在那一边看你回收GC,一边看你重新加载。这两件事情,肯定是互相矛盾的,也是影响性能的一个很重要的原因。

篇2:Android异步加载全解析之引入一级缓存

内存缓存LruCache所使用的内存缓存大小是由开发者决定的,开发者需要根据图像的使用率、分辨率、访问频率、设备性能等很多因素进行考虑。这个平衡点经常需要很多经验和测试来决定。使用LruCache非常简单:

private LruCachemMemoryCaches;// 获取应用内存int maxMemory = (int) Runtime.getRuntime.maxMemory();// 分配cacheint cacheSize = maxMemory / 10;mMemoryCaches = new LruCache(cacheSize) {@Overrideprotected int sizeOf(String key, Bitmap value) { return value.getByteCount();} };// 从LruCache获取中获取缓存对象public Bitmap getBitmapFromMemoryCaches(String url) { return mMemoryCaches.get(url);}// 增加缓存对象到LruCachepublic void addBitmapToMemoryCaches(String url,Bitmap bitmap) { if (getBitmapFromMemoryCaches(url) == null) { mMemoryCaches.put(url, bitmap); }}

首先,我们需要声明LruCache,接着,通过LruCache的构造方法创建缓存对象,并为其分配cacheSize,这个cacheSize通常我们需要通过Runtime来获取,获取当前系统分给App的可用内存,并将这些内存的一部分用做LruCache缓存。LruCache中必须重写sizeOf方法,通过这个方法,LruCache可以获取每个缓存对象的大小,子类必须重写,因为默认的LruCache获取的是缓存的个数。。。 。 最后,我们提供两个方法getBitmapFromMemoryCaches和addBitmapToMemoryCaches分别用来获取和增加内存缓存到LruCache。 等等,我们好像还没写释放内存的方法,对,不用你写了,Lru算法可以保证cacheSize不会OOM,一旦超过这个大小,GC就会回收时间最长的对象,释放空间。

篇3:Android异步加载全解析之引入一级缓存

针对这样一个非常需要找到一个彼此平衡点的问题,Google提供了一套内存缓存技术。内存缓存技术对那些大量占用应用程序宝贵内存的图片提供了快速访问的方法。其中最核心的类是LruCache 。这个类非常适合用来缓存图片,它的主要算法原理是把最近使用的对象用强引用存储在 LinkedHashMap 中,并且把最近最少使用的对象在缓存值达到预设定值之前从内存中移除。LruCache 是在support-v4中才引入的,在引入LruCache 之前,Google建议的是使用软引用或弱引用 (SoftReference or WeakReference)来进行内存缓存。但是从Android 2.3开始,GC算法修改,软引用与弱引用同样会优先被GC回收,所以这种方法也就没有太高的使用价值了,现在网上很多还在继续使用SoftReference 和WeakReference的文章,大多都是过时的文章,建议大家跟上党的步伐,与时俱进。

篇4:Android异步加载全解析之引入一级缓存

OK,在了解了关于缓存的基础信息后,我们回到现在这个例子,想想怎么利用缓存来进行异步处理的优化。首先,ListView、GridView这些娇生惯养的玩意儿,碰不得摔不得,更不能在它滚的开心的时候,你还在后面拼命玩加载。所以,第一个重点,滚的时候就让它开心的滚,滚完了再开始加载。

滚完再加载

要实现这一点,我们可以通过给Adapter增加AbsListView.OnScrollListener接口来实现。 当然,还有一点需要注意,第一次初始化的时候,一定要手动来加载图片,不然系统判断你没滚,只能调用onScroll方法,不会调用onScrollStateChanged方法。而且我们也需要在onScroll方法中来不断获取可见的Item。特别要注意的是visibleItemCount,只要大于0的时候,才认为是开始显示图片了。

@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) { if (scrollState == SCROLL_STATE_IDLE) { mImageLoader.loadImages(mStart, mEnd); } else { mImageLoader.cancelAllTasks; }}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { mStart = firstVisibleItem; mEnd = firstVisibleItem + visibleItemCount; if (mFirstFlag && visibleItemCount >0) { mImageLoader.loadImages(mStart, mEnd); mFirstFlag = false; }}

加载显示的项目

加载数据的时候,获取第一个能显示的Item和最后一个可见的Item,只加载这一部分。所以我们创建一个方法——loadImages(int start, int end)。这个方法用来加载从start到end之间的Item数据。 加载的时候,先从内存缓存中去取,如果有,那说明最近已经加载过了,那直接加载就好了,如果没有取到,那就开启synctask去下载。

public void loadImages(int start, int end) { for (int i = start; i < end; i++) { String url = Images.IMAGE_URLS[i]; Bitmap bitmap = getBitmapFromMemoryCaches(url); if (bitmap == null) {ASyncDownloadImage task = new ASyncDownloadImage(url);mTasks.add(task);task.execute(url); } else {ImageView imageView = (ImageView) mListView.findViewWithTag(url);imageView.setImageBitmap(bitmap); } }}

这里我们在设置图片的时候,直接通过findViewWithTag,通过url来找到相应的Imageview,这里与之前不同是因为我们这里是按照start到end来进行加载,直接从ListView对象中获取对应的Imageview比较简单。

下载与Asynctask

下载依然是使用老方法:

private static Bitmap getBitmapFromUrl(String urlString) { Bitmap bitmap; InputStream is = null; try { URL url = new URL(urlString); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); is = new BufferedInputStream(conn.getInputStream()); bitmap = BitmapFactory.decodeStream(is); conn.disconnect(); return bitmap; } catch (Exception e) { e.printStackTrace(); } finally { try {if (is != null) is.close(); } catch (IOException e) { } } return null;}

Asynctask也与之前基本类似:

class ASyncDownloadImage extends AsyncTask{ private String url; public ASyncDownloadImage(String url) { this.url = url; } @Override protected Bitmap doInBackground(String... params) { url = params[0]; Bitmap bitmap = getBitmapFromUrl(url); if (bitmap != null) {addBitmapToMemoryCaches(url, bitmap); } return bitmap; } @Override protected void onPostExecute(Bitmap bitmap) { super.onPostExecute(bitmap); ImageView imageView = (ImageView) mListView.findViewWithTag(url); if (imageView != null && bitmap != null) {imageView.setImageBitmap(bitmap); } mTasks.remove(this); }}

唯一不同的是,我们在下载好图像之后,会将图像加载到Lrucache。

组装

OK,万事具备,准备刷代码。在刷之前,我们先来重新整理下思路,首先,在Adapter中,一加载ListView,就开始下载显示范围内的Item的图像,这时候缓存中当然没有,所以都去下载了,下完了就显示在Item中,并缓存起来,如果还没下完,你就迫不及待的滚起来了,那么立即取消所有task,让ListView欢快的滚,滚完之后,继续加载。 OK,该讲的都讲了,下面我们开始刷代码了,一切尽在不言中,只有代码最懂你。

package com.imooc.listviewacyncloader;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.AsyncTask;import android.util.LruCache;import android.widget.ImageView;import android.widget.ListView;import java.io.BufferedInputStream;import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;import java.util.HashSet;import java.util.Set;public class ImageLoaderWithCaches { private Set mTasks; private LruCachemMemoryCaches; private ListView mListView; public ImageLoaderWithCaches(ListView listview) { this.mListView = listview; mTasks = new HashSet(); int maxMemory = (int) Runtime.getRuntime().maxMemory(); int cacheSize = maxMemory / 10; mMemoryCaches = new LruCache(cacheSize) {@Overrideprotected int sizeOf(String key, Bitmap value) { return value.getByteCount();} }; } public void showImage(String url, ImageView imageView) { Bitmap bitmap = getBitmapFromMemoryCaches(url); if (bitmap == null) {imageView.setImageResource(R.drawable.ic_launcher); } else {imageView.setImageBitmap(bitmap); } } public Bitmap getBitmapFromMemoryCaches(String url) { return mMemoryCaches.get(url); } public void addBitmapToMemoryCaches(String url,Bitmap bitmap) { if (getBitmapFromMemoryCaches(url) == null) {mMemoryCaches.put(url, bitmap); } } public void loadImages(int start, int end) { for (int i = start; i < end; i++) {String url = Images.IMAGE_URLS[i];Bitmap bitmap = getBitmapFromMemoryCaches(url);if (bitmap == null) { ASyncDownloadImage task = new ASyncDownloadImage(url); mTasks.add(task); task.execute(url);} else { ImageView imageView = (ImageView) mListView.findViewWithTag(url); imageView.setImageBitmap(bitmap);} } } private static Bitmap getBitmapFromUrl(String urlString) { Bitmap bitmap; InputStream is = null; try {URL url = new URL(urlString);HttpURLConnection conn = (HttpURLConnection) url.openConnection();is = new BufferedInputStream(conn.getInputStream());bitmap = BitmapFactory.decodeStream(is);conn.disconnect();return bitmap; } catch (Exception e) {e.printStackTrace(); } finally {try { if (is != null) is.close();} catch (IOException e) {} } return null; } public void cancelAllTasks() { if (mTasks != null) {for (ASyncDownloadImage task : mTasks) { task.cancel(false);} } } class ASyncDownloadImage extends AsyncTask{ private String url; public ASyncDownloadImage(String url) {this.url = url; } @Override protected Bitmap doInBackground(String... params) {url = params[0];Bitmap bitmap = getBitmapFromUrl(url);if (bitmap != null) { addBitmapToMemoryCaches(url, bitmap);}return bitmap; } @Override protected void onPostExecute(Bitmap bitmap) {super.onPostExecute(bitmap);ImageView imageView = (ImageView) mListView.findViewWithTag(url);if (imageView != null && bitmap != null) { imageView.setImageBitmap(bitmap);}mTasks.remove(this); } }}

下面是Adapter的代码:

package com.imooc.listviewacyncloader;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.AbsListView;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.ListView;import java.util.List;public class MyAdapterUseCaches extends BaseAdapter implements AbsListView.OnScrollListener { private LayoutInflater mInflater; private ListmData; private ImageLoaderWithCaches mImageLoader; private int mStart = 0, mEnd = 0; private boolean mFirstFlag; public MyAdapterUseCaches(Context context, Listdata, ListView listView) { this.mData = data; mInflater = LayoutInflater.from(context); mImageLoader = new ImageLoaderWithCaches(listView); mImageLoader.loadImages(mStart, mEnd); mFirstFlag = true; listView.setOnScrollListener(this); } @Override public int getCount() { return mData.size(); } @Override public Object getItem(int position) { return mData.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { String url = mData.get(position); ViewHolder viewHolder = null; if (convertView == null) {viewHolder = new ViewHolder();convertView = mInflater.inflate(R.layout.listview_item, null);viewHolder.imageView = (ImageView) convertView.findViewById(R.id.iv_lv_item);convertView.setTag(viewHolder); } else {viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.imageView.setTag(url); viewHolder.imageView.setImageResource(R.drawable.ic_launcher); mImageLoader.showImage(url, viewHolder.imageView); return convertView; } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (scrollState == SCROLL_STATE_IDLE) {mImageLoader.loadImages(mStart, mEnd); } else {mImageLoader.cancelAllTasks(); } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { mStart = firstVisibleItem; mEnd = firstVisibleItem + visibleItemCount; if (mFirstFlag && visibleItemCount >0) {mImageLoader.loadImages(mStart, mEnd);mFirstFlag = false; } } public class ViewHolder { public ImageView imageView; }}

是不是非常简单,现在引入缓存了,下载过的图片会暂时保存在内存中,妈妈再也不用担心你OOM啦,

我们下拉试试,下载完的图片再次出现也可以马上加载了,除非滑动太多导致GC。

可以就看见,我们的这次利用缓存进行加载有这样几个特点: 1、初始化的时候加载 2、滑动的时候才加载 3、加载的内容暂存缓存中 4、只加载显示的区域

篇5:Android 图像异步加载之AndroidUniversalImageLoader

项目地址:github.com/nostra13/Android-Universal-Image-Loader UIL(Universal-Image-Loader)异步图像加载、缓存和显示.这个图片异步加载并缓存的类已经被很多开发者所使用,是最常用的几个开源库之一,主流的应用,随便反编译几个火的项目,都可以见到它的身影, 同类类库(Picasso),尽管Picasso拥有更好的API,但其缺乏自定义。而使用UIL构建器几乎可以配置所有(其中最重要的就是在抓取和缓存大型图片时,Picasso会失败)。

特点: 多线程加载图像Multithread image loading (async or sync)宽泛的自定义配置Wide customization of ImageLoader's configuration (thread executors, downloader, decoder, memory and disk cache, display image options, etc.)Many customization options for every display image call (stub images, caching switch, decoding options, Bitmap processing and displaying, etc.)图像缓存Image caching in memory and/or on disk (device's file system or SD card)加载过程监听Listening loading process (including downloading progress) 简单描述一下这个项目的结构:每一个图片的加载和显示任务都运行在独立的线程中,除非这个图片缓存在内存中,这种情况下图片会立即显示。如果需要的图片缓存在本地,他们会开启一个独立的线程队列。如果在缓存中没有正确的图片,任务线程会从线程池中获取,因此,快速显示缓存图片时不会有明显的障碍。

由于源码中不管是loadImageSync还是loadImage最后都会通过displayImage来加载。那我们看看其流程:

篇6:Android 图像异步加载之AndroidUniversalImageLoader

安装:

maven:

com.nostra13.universalimageloaderuniversal-image-loader1.9.3

Gradle:

compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.3'

添加网络和SD卡权限:

由于是使用过程中会图片获取要通过网络,并且有缓存设置,所以这2个权限必须要有。

预配置Application or Activity class (before the first usage of ImageLoader)

// Create global configuration and initialize ImageLoader with this config ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this)....build(); ImageLoader.getInstance().init(config);

Android Glide源码解析

android 数据存储之SharedPreferences

考研全流程解析下半年

一级注册消防工程师前景解析

HR筛选简历内幕全解析

人生得意须尽欢全诗解析

论文答辩开场白自述及问题的全解析

选择参考:几大特色工科院校全解析

麟之趾 诗经全诗赏析

心理学考研之大纲解析与指导

Android异步加载全解析之引入一级缓存(精选6篇)

欢迎下载DOC格式的Android异步加载全解析之引入一级缓存,但愿能给您带来参考作用!
推荐度: 推荐 推荐 推荐 推荐 推荐
点击下载文档 文档为doc格式

猜你喜欢

NEW
点击下载本文文档