前言:
本篇介绍Android中的各种缓存机制和缓存框架,同样借鉴网上的一些知识总结分享给大家。
HR经常问到的缓存机制?
客户端缓存机制是android应用开发中非常重要的一项工作了,使用缓存机制不仅可以为客户节省流量,同时提高了用户体验,比如今日头条的离线模式,就是通过缓存机制实现的,那么缓存机制分为2种。文字缓存和多媒体文件缓存。
咱们先来说文字缓存:
1、将于服务器交互得到的json数据或者xml数据存入sd卡中,并在数据库添加该数据的记录。添加数据库记录时,可以提供2个字段,请求到的Url和本地保存后的文件地址,每次加载数据之前都会根据Url在数据库中检索。
ps:本段中提到存入sd卡,可能有的小伙伴不知道,这里说一下~
首先获取sdcard路径:
1
|
Environment.getExternalStorageDirectory()
|
判断sdcard状态:
1
|
Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
|
保存到sd卡: filename 文件名 content内容
1
2
3
4
5
6
|
public
void
saveToSDCard(String filename,String content)
throws
Exception{
File file=
new
File(Environment.getExternalStorageDirectory(), filename);
OutputStream out=
new
FileOutputStream(file);
out.write(content.getBytes());
out.close();
}
|
1
2
3
4
|
<!-- 在SDCard中创建于删除文件的权限 -->
<uses-permission android:name=
"android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
>
<!-- 往SDCard中写入数据的权限 -->
<uses-permission android:name=
"android.permission.WRITE_EXTERNAL_STORAGE"
> </uses-permission></uses-permission>
|
ps:这里没有保存到文件,是先保存到list>中,写入数据库,每次查询数据库获取数据;
之后就是多媒体_图片缓存了(本地缓存):
缓存图片可以根据当前日期、时间为名字缓存到sd卡中的指定图片缓存目录,同时数据库中左相应记录,记录办法可以采用俩个关键字段控制,一个字段是该图片的URL地址,另一个是该字段的图片本机地址,取图片时根据URL在数据中检索,如果没有则连接服务器下载,下载之后再服务器中做出相应记录。
ps:如何缓存到sd卡中呢?其实和文字缓存一样的思路;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
/** 保存方法 */
public
void
saveBitmap(Bitmap bm, String <span style=
"font-family: Arial, Helvetica, sans-serif;"
>picName</span>) {
Log.e(TAG,
"保存图片"
);
File f =
new
File(<span style=
"font-family: Arial, Helvetica, sans-serif;"
>Environment.getExternalStorageDirectory()</span>, picName);
//保存路径和图片名称(上文说的日期和时间可以作为)
if
(f.exists()) {
f.delete();
}
try
{
FileOutputStream out =
new
FileOutputStream(f);
bm.compress(Bitmap.CompressFormat.PNG,
90
, out);
out.flush();
out.close();
Log.i(TAG,
"已经保存"
);
}
catch
(FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch
(IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
|
三级缓存:
内存缓存(从内存中获取图片显示)、==》本地缓存(内存中没有从sd卡获取)、==》网络缓存(从网络下载并保存入本地和内存);
ps:从sd卡获取图片是放在子线程里面执行的,否则快速滑屏的话不够流畅!
一、Lrucache缓存:
核心的类是LruCache (此类在android-support-v4的包中提供) 。这个类非常适合用来缓存图片,它的主要算法原理是把最近使用的对象用强引用存储在 LinkedHashMap 中,并且把最近最少使用的对象在缓存值达到预设定值之前从内存中移除。
实现思路:
(1).要先设置缓存图片的内存大小,基本上设置为手机内存的1/8,手机内存的获取方式:int MAXMEMONRY = (int) (Runtime.getRuntime() .maxMemory() / 1024);
(2).LruCache里面的键值对分别是URL和对应的图片;
(3).重写了一个叫做sizeOf的方法,返回的是图片数量。
它的使用:
1、初始化Lrucache
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
|
import
android.app.ActivityManager;
import
android.app.Application;
import
android.content.Context;
/**
* application
* @author hao
*
*/
public
class
MyApplication
extends
Application{
@Override
public
void
onCreate() {
// TODO Auto-generated method stub
super
.onCreate();
}
/**
* @description
*
* @param context
* @return 得到需要分配的缓存大小,这里用八分之一的大小来做
*/
public
int
getMemoryCacheSize() {
// Get memory class of this device, exceeding this amount will throw an
// OutOfMemory exception.
final
int
memClass = ((ActivityManager)getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
// Use 1/8th of the available memory for this memory cache.
return
1024
*
1024
* memClass /
8
;
}
}
|
2、初始化类
1
2
3
4
5
6
7
8
9
|
final
int
memoryCache = ((KaleApplication) getApplication()).getMemoryCacheSize();
Log.d(TAG,
"cache size = "
+ memoryCache /
1024
/
1024
+
"M"
);
mMemoryCache =
new
LruCache<string, bitmap=
""
>(memoryCache) {
@Override
protected
int
sizeOf(String key, Bitmap bitmap) {
// 重写此方法来衡量每张图片的大小,默认返回图片数量。
return
bitmap.getByteCount() /
1024
;
}
};
// 初始化</string,>
|
3、添加删除和添加操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
/**
* @description 将bitmap添加到内存中去
*
* @param key
* @param bitmap
*/
public
void
addBitmapToMemoryCache(String key, Bitmap bitmap) {
if
(getBitmapFromMemCache(key) ==
null
) {
mMemoryCache.put(key, bitmap);
}
}
/**
* @description 通过key来从内存缓存中获得bitmap对象
*
* @param key
* @return
*/
private
Bitmap getBitmapFromMemCache(String key) {
return
mMemoryCache.get(key);
}
|
4、从网络上缓存并添加入缓存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<span style=
"white-space:pre"
> </span>
/**
* @description 将bitmap加载到imageview中去
*
* @param resId
* @param imageView
*/
public
void
loadBitmapToImageView(String url, ImageView imageView) {
final
Bitmap bitmap = getBitmapFromMemCache(
"img"
);
// 先看这个资源在不在内存中,如果在直接读取为bitmap,否则返回null
if
(bitmap !=
null
) {
Log.d(TAG,
"in memory"
);
imageView.setImageBitmap(bitmap);
}
else
{
Log.d(TAG,
"not in memory"
);
imageView.setImageResource(R.drawable.ic_launcher);
// 如果没有在内存中,先显示默认的图片,然后启动线程去下载图片
BitmapWorkerTask task =
new
BitmapWorkerTask(imageView);
task.execute(url);
// 启动线程,从网络下载图片,下载后加入缓存
}
}
|
ps:判断图片是否已经进行了缓存操作。图片如果在内存中就直接赋值,没有启动线程重新获取。
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
|
import
java.io.IOException;
import
java.net.HttpURLConnection;
import
java.net.MalformedURLException;
import
java.net.URL;
import
android.graphics.Bitmap;
import
android.graphics.BitmapFactory;
import
android.os.AsyncTask;
import
android.widget.ImageView;
public
class
BitmapWorkerTask
extends
AsyncTask<string, bitmap=
""
>{
private
MainActivity mActivity;
private
ImageView mImageView;
public
BitmapWorkerTask(ImageView imageView) {
mImageView = imageView;
mActivity = (MainActivity) imageView.getContext();
}
/**
* 下载图片
*/
@Override
protected
Bitmap doInBackground(String... params) {
Bitmap bitmap =
null
;
HttpURLConnection con =
null
;
try
{
URL url =
new
URL(params[
0
]);
con = (HttpURLConnection) url.openConnection();
con.setConnectTimeout(
10
*
1000
);
con.setReadTimeout(
10
*
1000
);
bitmap = BitmapFactory.decodeStream(con.getInputStream());
//添加到内存
mActivity.addBitmapToMemoryCache(
"img"
, bitmap);
}
catch
(MalformedURLException e) {
e.printStackTrace();
}
catch
(IOException e) {
e.printStackTrace();
}
finally
{
if
(con !=
null
) {
con.disconnect();
}
}
return
bitmap;
}
@Override
protected
void
onPostExecute(Bitmap result) {
super
.onPostExecute(result);
if
(result !=
null
) {
mImageView.setImageBitmap(result);
}
}
}
</string,>
|
让我们最后看一下效果吧!!!