http://www.codeceo.com/article/asimplecache-android-cache.html
ASimpleCache可以缓存哪些东西
ASimpleCache基本可以缓存常用的Android对象,包括但不限于以下几种类型:
- 普通字符串
- JSON对象
- 经过序列化的Java对象
- 字节数组
ASimpleCache的特点
- 轻量级,只有一个Java文件
- 完整而灵活的配置,可以配置缓存路径,缓存大小,缓存数量,缓存超时时间等。
- 超时缓存自动失效,并从内存中自动删除。
- 多进程的支持
在Android开发中,我们可以用ASimpleCache来替换SharePreference配置文件,特别是如果你的应用经常要从互联网上读取数据,那么利用ASimpleCache可以缓存这些请求数据,等一段时间失效后再去重新读取,这样可以减少客户端流量,同时减少服务器并发量。
一、android缓存的介绍
Android开发本质上就是手机和互联网中的web服务器之间进行通信,就必然需要从服务端获取数据,而反复通过网络获取数据是比较耗时的,特别是访问比较多的时候,会极大影响了性能,Android中可通过二级缓存来减少频繁的网络操作,减少流量、提升性能。
1.二级缓存定义:
当Android端需要获得数据时比如获取网络中的图片,我们首先从内存中查找(按键查找),内存中没有的再从磁盘文件或sqlite中去查找,若磁盘中也没有才通过网络获取;当获得来自网络的数据,就以key-value对的方式先缓存到内存(一级缓存),同时缓存到文件或sqlite中(二级缓存)。注意:内存缓存会造成堆内存泄露,所有一级缓存通常要严格控制缓存的大小,一般控制在系统内存的1/4。
2.保存在本地了怎么更新网络数据呢?
理解了二级缓存大家可能会有个问题网络中的数据是变化的,数据一旦放入缓存中,再取该数据就是从缓存中获得,这样岂不是不能体现数据的变化?我们在缓存数据时会设置有效时间,比如说30分钟,若超过这个时间数据就失效并释放空间,然后重新请求网络中的数据。有的童鞋就问30分钟内咋办?那好吧,我也没招了,只有下拉刷新了吧,实际上这不是问题。
二、本篇就介绍下Acache缓存
ACache是一个为android制定的轻量级的开源缓存框架。轻量到只有一个java文件(由十几个类精简而来)。
1、它可以缓存什么东西?
普通的字符串、json、序列化的java对象,和字节数字。
2、它有什么特色?
特色主要是:
1:轻,轻到只有一个JAVA文件。
2:可配置,可以配置缓存路径,缓存大小,缓存数量等。
3:可以设置缓存超时时间,缓存超时自动失效,并被删除。
4:多进程的支持。
3.使用
‹𝟙›初始化ACache组件
ACacheacache=ACache.get(context)
或
ACacheacache=ACache.get(context,max_size,max_count)
参数说明:
max_size:设置限制缓存大小,默认为50M
max_count:设置缓存数据的数量,默认不限制
‹𝟚›设置缓存数据
acache.put(key,data,time)或acache.put(key,data)
将数据同时上存入一级缓存(内存Map)和二级缓存(文件)中
参数说明:
Key:为存入缓存的数据设置唯一标识,取数据时就根据key来获得的
Data:要存入的数据,acache支持的数据类型如图所示:
有String、可序列化的对象、字节数组、Drawable等 Time:设置缓存数据的有效时间,单位秒

‹𝟛›从缓存中取数据
提供一系列getAsXXX()方法,如图所示。
根据不同存入数据,调用不同的方法取数据
ACache

‹𝟜›ACache代码片

1 import android.content.Context; 2 import android.graphics.Bitmap; 3 import android.graphics.BitmapFactory; 4 import android.graphics.Canvas; 5 import android.graphics.PixelFormat; 6 import android.graphics.drawable.BitmapDrawable; 7 import android.graphics.drawable.Drawable; 8 9 import org.json.JSONArray; 10 import org.json.JSONObject; 11 12 import java.io.BufferedReader; 13 import java.io.BufferedWriter; 14 import java.io.ByteArrayInputStream; 15 import java.io.ByteArrayOutputStream; 16 import java.io.File; 17 import java.io.FileInputStream; 18 import java.io.FileNotFoundException; 19 import java.io.FileOutputStream; 20 import java.io.FileReader; 21 import java.io.FileWriter; 22 import java.io.IOException; 23 import java.io.InputStream; 24 import java.io.ObjectInputStream; 25 import java.io.ObjectOutputStream; 26 import java.io.OutputStream; 27 import java.io.RandomAccessFile; 28 import java.io.Serializable; 29 import java.util.Collections; 30 import java.util.HashMap; 31 import java.util.Map; 32 import java.util.Set; 33 import java.util.concurrent.atomic.AtomicInteger; 34 import java.util.concurrent.atomic.AtomicLong; 35 36 /** 37 * Created by annie on 2017/3/26. 38 */ 39 40 public class ACache { 41 public static final int TIME_HOUR = 60 * 60; 42 public static final int TIME_DAY = TIME_HOUR * 24; 43 private static final int MAX_SIZE = 1000 * 1000 * 50; // 50 mb 44 private static final int MAX_COUNT = Integer.MAX_VALUE; // 不限制存放数据的数量 45 private static Map<String, ACache> mInstanceMap = new HashMap<String, ACache>(); 46 private ACacheManager mCache; 47 48 public static ACache get(Context ctx) { 49 return get(ctx, "ACache"); 50 } 51 52 public static ACache get(Context ctx, String cacheName) { 53 File f = new File(ctx.getCacheDir(), cacheName); 54 return get(f, MAX_SIZE, MAX_COUNT); 55 } 56 57 public static ACache get(File cacheDir) { 58 return get(cacheDir, MAX_SIZE, MAX_COUNT); 59 } 60 61 public static ACache get(Context ctx, long max_zise, int max_count) { 62 File f = new File(ctx.getCacheDir(), "ACache"); 63 return get(f, max_zise, max_count); 64 } 65 66 public static ACache get(File cacheDir, long max_zise, int max_count) { 67 ACache manager = mInstanceMap.get(cacheDir.getAbsoluteFile() + myPid()); 68 if (manager == null) { 69 manager = new ACache(cacheDir, max_zise, max_count); 70 mInstanceMap.put(cacheDir.getAbsolutePath() + myPid(), manager); 71 } 72 return manager; 73 } 74 75 private static String myPid() { 76 return "_" + android.os.Process.myPid(); 77 } 78 79 private ACache(File cacheDir, long max_size, int max_count) { 80 if (!cacheDir.exists() && !cacheDir.mkdirs()) { 81 throw new RuntimeException("can't make dirs in " + cacheDir.getAbsolutePath()); 82 } 83 mCache = new ACacheManager(cacheDir, max_size, max_count); 84 } 85 86 87 88 /** 89 * Provides a means to save a cached file before the data are available. 90 * Since writing about the file is complete, and its close method is called, 91 * its contents will be registered in the cache. Example of use: 92 * 93 * ACache cache = new ACache(this) try { OutputStream stream = 94 * cache.put("myFileName") stream.write("some bytes".getBytes()); // now 95 * update cache! stream.close(); } catch(FileNotFoundException e){ 96 * e.printStackTrace() } 97 */ 98 class xFileOutputStream extends FileOutputStream { 99 File file; 100 101 public xFileOutputStream(File file) throws FileNotFoundException { 102 super(file); 103 this.file = file; 104 } 105 106 public void close() throws IOException { 107 super.close(); 108 mCache.put(file); 109 } 110 } 111 112 // ======================================= 113 // ============ String数据 读写 ============== 114 // ======================================= 115 /** 116 * 保存 String数据 到 缓存中 117 * 118 * @param key 119 * 保存的key 120 * @param value 121 * 保存的String数据 122 */ 123 public void put(String key, String value) { 124 File file = mCache.newFile(key); 125 BufferedWriter out = null; 126 try { 127 out = new BufferedWriter(new FileWriter(file), 1024); 128 out.write(value); 129 } catch (IOException e) { 130 e.printStackTrace(); 131 } finally { 132 if (out != null) { 133 try { 134 out.flush(); 135 out.close(); 136 } catch (IOException e) { 137 e.printStackTrace(); 138 } 139 } 140 mCache.put(file); 141 } 142 } 143 144 /** 145 * 保存 String数据 到 缓存中 146 * 147 * @param key 148 * 保存的key 149 * @param value 150 * 保存的String数据 151 * @param saveTime 152 * 保存的时间,单位:秒 153 */ 154 public void put(String key, String value, int saveTime) { 155 put(key, Utils.newStringWithDateInfo(saveTime, value)); 156 } 157 158 /** 159 * 读取 String数据 160 * 161 * @param key 162 * @return String 数据 163 */ 164 public String getAsString(String key) { 165 File file = mCache.get(key); 166 if (!file.exists()) 167 return null; 168 boolean removeFile = false; 169 BufferedReader in = null; 170 try { 171 in = new BufferedReader(new FileReader(file)); 172 String readString = ""; 173 String currentLine; 174 while ((currentLine = in.readLine()) != null) { 175 readString += currentLine; 176 } 177 if (!Utils.isDue(readString)) { 178 return Utils.clearDateInfo(readString); 179 } else { 180 removeFile = true; 181 return null; 182 } 183 } catch (IOException e) { 184 e.printStackTrace(); 185 return null; 186 } finally { 187 if (in != null) { 188 try { 189 in.close(); 190 } catch (IOException e) { 191 e.printStackTrace(); 192 } 193 } 194 if (removeFile) 195 remove(key); 196 } 197 } 198 199 // ======================================= 200 // ============= JSONObject 数据 读写 ============== 201 // ======================================= 202 /** 203 * 保存 JSONObject数据 到 缓存中 204 * 205 * @param key 206 * 保存的key 207 * @param value 208 * 保存的JSON数据 209 */ 210 public void put(String key, JSONObject value) { 211 put(key, value.toString()); 212 } 213 214 /** 215 * 保存 JSONObject数据 到 缓存中 216 * 217 * @param key 218 * 保存的key 219 * @param value 220 * 保存的JSONObject数据 221 * @param saveTime 222 * 保存的时间,单位:秒 223 */ 224 public void put(String key, JSONObject value, int saveTime) { 225 put(key, value.toString(), saveTime); 226 } 227 228 /** 229 * 读取JSONObject数据 230 * 231 * @param key 232 * @return JSONObject数据 233 */ 234 public JSONObject getAsJSONObject(String key) { 235 String JSONString = getAsString(key); 236 try { 237 JSONObject obj = new JSONObject(JSONString); 238 return obj; 239 } catch (Exception e) { 240 e.printStackTrace(); 241 return null; 242 } 243 } 244 245 // ======================================= 246 // ============ JSONArray 数据 读写 ============= 247 // ======================================= 248 /** 249 * 保存 JSONArray数据 到 缓存中 250 * 251 * @param key 252 * 保存的key 253 * @param value 254 * 保存的JSONArray数据 255 */ 256 public void put(String key, JSONArray value) { 257 put(key, value.toString()); 258 } 259 260 /** 261 * 保存 JSONArray数据 到 缓存中 262 * 263 * @param key 264 * 保存的key 265 * @param value 266 * 保存的JSONArray数据 267 * @param saveTime 268 * 保存的时间,单位:秒 269 */ 270 public void put(String key, JSONArray value, int saveTime) { 271 put(key, value.toString(), saveTime); 272 } 273 274 /** 275 * 读取JSONArray数据 276 * 277 * @param key 278 * @return JSONArray数据 279 */ 280 public JSONArray getAsJSONArray(String key) { 281 String JSONString = getAsString(key); 282 try { 283 JSONArray obj = new JSONArray(JSONString); 284 return obj; 285 } catch (Exception e) { 286 e.printStackTrace(); 287 return null; 288 } 289 } 290 291 // ======================================= 292 // ============== byte 数据 读写 ============= 293 // ======================================= 294 /** 295 * 保存 byte数据 到 缓存中 296 * 297 * @param key 298 * 保存的key 299 * @param value 300 * 保存的数据 301 */ 302 public void put(String key, byte[] value) { 303 File file = mCache.newFile(key); 304 FileOutputStream out = null; 305 try { 306 out = new FileOutputStream(file); 307 out.write(value); 308 } catch (Exception e) { 309 e.printStackTrace(); 310 } finally { 311 if (out != null) { 312 try { 313 out.flush(); 314 out.close(); 315 } catch (IOException e) { 316 e.printStackTrace(); 317 } 318 } 319 mCache.put(file); 320 } 321 } 322 323 /** 324 * Cache for a stream 325 * 326 * @param key 327 * the file name. 328 * @return OutputStream stream for writing data. 329 * @throws FileNotFoundException 330 * if the file can not be created. 331 */ 332 public OutputStream put(String key) throws FileNotFoundException { 333 return new xFileOutputStream(mCache.newFile(key)); 334 } 335 336 /** 337 * 338 * @param key 339 * the file name. 340 * @return (InputStream or null) stream previously saved in cache. 341 * @throws FileNotFoundException 342 * if the file can not be opened 343 */ 344 public InputStream get(String key) throws FileNotFoundException { 345 File file = mCache.get(key); 346 if (!file.exists()) 347 return null; 348 return new FileInputStream(file); 349 } 350 351 /** 352 * 保存 byte数据 到 缓存中 353 * 354 * @param key 355 * 保存的key 356 * @param value 357 * 保存的数据 358 * @param saveTime 359 * 保存的时间,单位:秒 360 */ 361 public void put(String key, byte[] value, int saveTime) { 362 put(key, Utils.newByteArrayWithDateInfo(saveTime, value)); 363 } 364 365 /** 366 * 获取 byte 数据 367 * 368 * @param key 369 * @return byte 数据 370 */ 371 public byte[] getAsBinary(String key) { 372 RandomAccessFile RAFile = null; 373 boolean removeFile = false; 374 try { 375 File file = mCache.get(key); 376 if (!file.exists()) 377 return null; 378 RAFile = new RandomAccessFile(file, "r"); 379 byte[] byteArray = new byte[(int) RAFile.length()]; 380 RAFile.read(byteArray); 381 if (!Utils.isDue(byteArray)) { 382 return Utils.clearDateInfo(byteArray); 383 } else { 384 removeFile = true; 385 return null; 386 } 387 } catch (Exception e) { 388 e.printStackTrace(); 389 return null; 390 } finally { 391 if (RAFile != null) { 392 try { 393 RAFile.close(); 394 } catch (IOException e) { 395 e.printStackTrace(); 396 } 397 } 398 if (removeFile) 399 remove(key); 400 } 401 } 402 403 // ======================================= 404 // ============= 序列化 数据 读写 =============== 405 // ======================================= 406 /** 407 * 保存 Serializable数据 到 缓存中 408 * 409 * @param key 410 * 保存的key 411 * @param value 412 * 保存的value 413 */ 414 public void put(String key, Serializable value) { 415 put(key, value, -1); 416 } 417 418 /** 419 * 保存 Serializable数据到 缓存中 420 * 421 * @param key 422 * 保存的key 423 * @param value 424 * 保存的value 425 * @param saveTime 426 * 保存的时间,单位:秒 427 */ 428 public void put(String key, Serializable value, int saveTime) { 429 ByteArrayOutputStream baos = null; 430 ObjectOutputStream oos = null; 431 try { 432 baos = new ByteArrayOutputStream(); 433 oos = new ObjectOutputStream(baos); 434 oos.writeObject(value); 435 byte[] data = baos.toByteArray(); 436 if (saveTime != -1) { 437 put(key, data, saveTime); 438 } else { 439 put(key, data); 440 } 441 } catch (Exception e) { 442 e.printStackTrace(); 443 } finally { 444 try { 445 oos.close(); 446 } catch (IOException e) { 447 } 448 } 449 } 450 451 /** 452 * 读取 Serializable数据 453 * 454 * @param key 455 * @return Serializable 数据 456 */ 457 public Object getAsObject(String key) { 458 byte[] data = getAsBinary(key); 459 if (data != null) { 460 ByteArrayInputStream bais = null; 461 ObjectInputStream ois = null; 462 try { 463 bais = new ByteArrayInputStream(data); 464 ois = new ObjectInputStream(bais); 465 Object reObject = ois.readObject(); 466 return reObject; 467 } catch (Exception e) { 468 e.printStackTrace(); 469 return null; 470 } finally { 471 try { 472 if (bais != null) 473 bais.close(); 474 } catch (IOException e) { 475 e.printStackTrace(); 476 } 477 try { 478 if (ois != null) 479 ois.close(); 480 } catch (IOException e) { 481 e.printStackTrace(); 482 } 483 } 484 } 485 return null; 486 487 } 488 489 // ======================================= 490 // ============== bitmap 数据 读写 ============= 491 // ======================================= 492 /** 493 * 保存 bitmap 到 缓存中 494 * 495 * @param key 496 * 保存的key 497 * @param value 498 * 保存的bitmap数据 499 */ 500 public void put(String key, Bitmap value) { 501 put(key, Utils.Bitmap2Bytes(value)); 502 } 503 504 /** 505 * 保存 bitmap 到 缓存中 506 * 507 * @param key 508 * 保存的key 509 * @param value 510 * 保存的 bitmap 数据 511 * @param saveTime 512 * 保存的时间,单位:秒 513 */ 514 public void put(String key, Bitmap value, int saveTime) { 515 put(key, Utils.Bitmap2Bytes(value), saveTime); 516 } 517 518 /** 519 * 读取 bitmap 数据 520 * 521 * @param key 522 * @return bitmap 数据 523 */ 524 public Bitmap getAsBitmap(String key) { 525 if (getAsBinary(key) == null) { 526 return null; 527 } 528 return Utils.Bytes2Bimap(getAsBinary(key)); 529 } 530 531 // ======================================= 532 // ============= drawable 数据 读写 ============= 533 // ======================================= 534 /** 535 * 保存 drawable 到 缓存中 536 * 537 * @param key 538 * 保存的key 539 * @param value 540 * 保存的drawable数据 541 */ 542 public void put(String key, Drawable value) { 543 put(key, Utils.drawable2Bitmap(value)); 544 } 545 546 /** 547 * 保存 drawable 到 缓存中 548 * 549 * @param key 550 * 保存的key 551 * @param value 552 * 保存的 drawable 数据 553 * @param saveTime 554 * 保存的时间,单位:秒 555 */ 556 public void put(String key, Drawable value, int saveTime) { 557 put(key, Utils.drawable2Bitmap(value), saveTime); 558 } 559 560 /** 561 * 读取 Drawable 数据 562 * 563 * @param key 564 * @return Drawable 数据 565 */ 566 public Drawable getAsDrawable(String key) { 567 if (getAsBinary(key) == null) { 568 return null; 569 } 570 return Utils.bitmap2Drawable(Utils.Bytes2Bimap(getAsBinary(key))); 571 } 572 573 /** 574 * 获取缓存文件 575 * 576 * @param key 577 * @return value 缓存的文件 578 */ 579 public File file(String key) { 580 File f = mCache.newFile(key); 581 if (f.exists()) 582 return f; 583 return null; 584 } 585 586 /** 587 * 移除某个key 588 * 589 * @param key 590 * @return 是否移除成功 591 */ 592 public boolean remove(String key) { 593 return mCache.remove(key); 594 } 595 596 /** 597 * 清除所有数据 598 */ 599 public void clear() { 600 mCache.clear(); 601 } 602 603 /** 604 * @title 缓存管理器 605 * @author 杨福海(michael) www.yangfuhai.com 606 * @version 1.0 607 */ 608 public class ACacheManager { 609 private final AtomicLong cacheSize; 610 private final AtomicInteger cacheCount; 611 private final long sizeLimit; 612 private final int countLimit; 613 private final Map<File, Long> lastUsageDates = Collections.synchronizedMap(new HashMap<File, Long>()); 614 protected File cacheDir; 615 616 private ACacheManager(File cacheDir, long sizeLimit, int countLimit) { 617 this.cacheDir = cacheDir; 618 this.sizeLimit = sizeLimit; 619 this.countLimit = countLimit; 620 cacheSize = new AtomicLong(); 621 cacheCount = new AtomicInteger(); 622 calculateCacheSizeAndCacheCount(); 623 } 624 625 /** 626 * 计算 cacheSize和cacheCount 627 */ 628 private void calculateCacheSizeAndCacheCount() { 629 new Thread(new Runnable() { 630 @Override 631 public void run() { 632 int size = 0; 633 int count = 0; 634 File[] cachedFiles = cacheDir.listFiles(); 635 if (cachedFiles != null) { 636 for (File cachedFile : cachedFiles) { 637 size += calculateSize(cachedFile); 638 count += 1; 639 lastUsageDates.put(cachedFile, cachedFile.lastModified()); 640 } 641 cacheSize.set(size); 642 cacheCount.set(count); 643 } 644 } 645 }).start(); 646 } 647 648 private void put(File file) { 649 int curCacheCount = cacheCount.get(); 650 while (curCacheCount + 1 > countLimit) { 651 long freedSize = removeNext(); 652 cacheSize.addAndGet(-freedSize); 653 654 curCacheCount = cacheCount.addAndGet(-1); 655 } 656 cacheCount.addAndGet(1); 657 658 long valueSize = calculateSize(file); 659 long curCacheSize = cacheSize.get(); 660 while (curCacheSize + valueSize > sizeLimit) { 661 long freedSize = removeNext(); 662 curCacheSize = cacheSize.addAndGet(-freedSize); 663 } 664 cacheSize.addAndGet(valueSize); 665 666 Long currentTime = System.currentTimeMillis(); 667 file.setLastModified(currentTime); 668 lastUsageDates.put(file, currentTime); 669 } 670 671 private File get(String key) { 672 File file = newFile(key); 673 Long currentTime = System.currentTimeMillis(); 674 file.setLastModified(currentTime); 675 lastUsageDates.put(file, currentTime); 676 677 return file; 678 } 679 680 private File newFile(String key) { 681 return new File(cacheDir, key.hashCode() + ""); 682 } 683 684 private boolean remove(String key) { 685 File image = get(key); 686 return image.delete(); 687 } 688 689 private void clear() { 690 lastUsageDates.clear(); 691 cacheSize.set(0); 692 File[] files = cacheDir.listFiles(); 693 if (files != null) { 694 for (File f : files) { 695 f.delete(); 696 } 697 } 698 } 699 700 /** 701 * 移除旧的文件 702 * 703 * @return 704 */ 705 private long removeNext() { 706 if (lastUsageDates.isEmpty()) { 707 return 0; 708 } 709 710 Long oldestUsage = null; 711 File mostLongUsedFile = null; 712 Set<Map.Entry<File, Long>> entries = lastUsageDates.entrySet(); 713 synchronized (lastUsageDates) { 714 for (Map.Entry<File, Long> entry : entries) { 715 if (mostLongUsedFile == null) { 716 mostLongUsedFile = entry.getKey(); 717 oldestUsage = entry.getValue(); 718 } else { 719 Long lastValueUsage = entry.getValue(); 720 if (lastValueUsage < oldestUsage) { 721 oldestUsage = lastValueUsage; 722 mostLongUsedFile = entry.getKey(); 723 } 724 } 725 } 726 } 727 728 long fileSize = calculateSize(mostLongUsedFile); 729 if (mostLongUsedFile.delete()) { 730 lastUsageDates.remove(mostLongUsedFile); 731 } 732 return fileSize; 733 } 734 735 private long calculateSize(File file) { 736 return file.length(); 737 } 738 } 739 740 /** 741 * @title 时间计算工具类 742 * @author 杨福海(michael) www.yangfuhai.com 743 * @version 1.0 744 */ 745 private static class Utils { 746 747 /** 748 * 判断缓存的String数据是否到期 749 * 750 * @param str 751 * @return true:到期了 false:还没有到期 752 */ 753 private static boolean isDue(String str) { 754 return isDue(str.getBytes()); 755 } 756 757 /** 758 * 判断缓存的byte数据是否到期 759 * 760 * @param data 761 * @return true:到期了 false:还没有到期 762 */ 763 private static boolean isDue(byte[] data) { 764 String[] strs = getDateInfoFromDate(data); 765 if (strs != null && strs.length == 2) { 766 String saveTimeStr = strs[0]; 767 while (saveTimeStr.startsWith("0")) { 768 saveTimeStr = saveTimeStr.substring(1, saveTimeStr.length()); 769 } 770 long saveTime = Long.valueOf(saveTimeStr); 771 long deleteAfter = Long.valueOf(strs[1]); 772 if (System.currentTimeMillis() > saveTime + deleteAfter * 1000) { 773 return true; 774 } 775 } 776 return false; 777 } 778 779 private static String newStringWithDateInfo(int second, String strInfo) { 780 return createDateInfo(second) + strInfo; 781 } 782 783 private static byte[] newByteArrayWithDateInfo(int second, byte[] data2) { 784 byte[] data1 = createDateInfo(second).getBytes(); 785 byte[] retdata = new byte[data1.length + data2.length]; 786 System.arraycopy(data1, 0, retdata, 0, data1.length); 787 System.arraycopy(data2, 0, retdata, data1.length, data2.length); 788 return retdata; 789 } 790 791 private static String clearDateInfo(String strInfo) { 792 if (strInfo != null && hasDateInfo(strInfo.getBytes())) { 793 strInfo = strInfo.substring(strInfo.indexOf(mSeparator) + 1, strInfo.length()); 794 } 795 return strInfo; 796 } 797 798 private static byte[] clearDateInfo(byte[] data) { 799 if (hasDateInfo(data)) { 800 return copyOfRange(data, indexOf(data, mSeparator) + 1, data.length); 801 } 802 return data; 803 } 804 805 private static boolean hasDateInfo(byte[] data) { 806 return data != null && data.length > 15 && data[13] == '-' && indexOf(data, mSeparator) > 14; 807 } 808 809 private static String[] getDateInfoFromDate(byte[] data) { 810 if (hasDateInfo(data)) { 811 String saveDate = new String(copyOfRange(data, 0, 13)); 812 String deleteAfter = new String(copyOfRange(data, 14, indexOf(data, mSeparator))); 813 return new String[] { saveDate, deleteAfter }; 814 } 815 return null; 816 } 817 818 private static int indexOf(byte[] data, char c) { 819 for (int i = 0; i < data.length; i++) { 820 if (data[i] == c) { 821 return i; 822 } 823 } 824 return -1; 825 } 826 827 private static byte[] copyOfRange(byte[] original, int from, int to) { 828 int newLength = to - from; 829 if (newLength < 0) 830 throw new IllegalArgumentException(from + " > " + to); 831 byte[] copy = new byte[newLength]; 832 System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength)); 833 return copy; 834 } 835 836 private static final char mSeparator = ' '; 837 838 private static String createDateInfo(int second) { 839 String currentTime = System.currentTimeMillis() + ""; 840 while (currentTime.length() < 13) { 841 currentTime = "0" + currentTime; 842 } 843 return currentTime + "-" + second + mSeparator; 844 } 845 846 /* 847 * Bitmap → byte[] 848 */ 849 private static byte[] Bitmap2Bytes(Bitmap bm) { 850 if (bm == null) { 851 return null; 852 } 853 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 854 bm.compress(Bitmap.CompressFormat.PNG, 100, baos); 855 return baos.toByteArray(); 856 } 857 858 /* 859 * byte[] → Bitmap 860 */ 861 private static Bitmap Bytes2Bimap(byte[] b) { 862 if (b.length == 0) { 863 return null; 864 } 865 return BitmapFactory.decodeByteArray(b, 0, b.length); 866 } 867 868 /* 869 * Drawable → Bitmap 870 */ 871 private static Bitmap drawable2Bitmap(Drawable drawable) { 872 if (drawable == null) { 873 return null; 874 } 875 // 取 drawable 的长宽 876 int w = drawable.getIntrinsicWidth(); 877 int h = drawable.getIntrinsicHeight(); 878 // 取 drawable 的颜色格式 879 Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; 880 // 建立对应 bitmap 881 Bitmap bitmap = Bitmap.createBitmap(w, h, config); 882 // 建立对应 bitmap 的画布 883 Canvas canvas = new Canvas(bitmap); 884 drawable.setBounds(0, 0, w, h); 885 // 把 drawable 内容画到画布中 886 drawable.draw(canvas); 887 return bitmap; 888 } 889 890 /* 891 * Bitmap → Drawable 892 */ 893 @SuppressWarnings("deprecation") 894 private static Drawable bitmap2Drawable(Bitmap bm) { 895 if (bm == null) { 896 return null; 897 } 898 BitmapDrawable bd=new BitmapDrawable(bm); 899 bd.setTargetDensity(bm.getDensity()); 900 return new BitmapDrawable(bm); 901 } 902 } 903 }
测试Activity:
1 import com.example.acachetest.util.ACache; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.os.Handler; 6 import android.os.SystemClock; 7 import android.widget.TextView; 8 9 public class MainActivity extends Activity { 10 private ACache aCache; 11 private TextView mTextView; 12 private Handler mHandler = new Handler(){ 13 public void handleMessage(android.os.Message msg) { 14 if(msg.what==1){ 15 mTextView.setText("开始保存"); 16 }else if(msg.what==2){ 17 initDate(); 18 }else{ 19 if(aCache.getAsString("newText")==null){ 20 mTextView.setText("没有保存的数据了,重新加载"); 21 } 22 } 23 }; 24 }; 25 26 @Override 27 protected void onCreate(Bundle savedInstanceState) { 28 super.onCreate(savedInstanceState); 29 setContentView(R.layout.activity_main); 30 mTextView = (TextView) findViewById(R.id.list); 31 initAcache(); 32 initDate(); 33 34 } 35 36 private void initDate() { 37 String cacheData = aCache.getAsString("newText");// 从缓存中取数据 38 39 if (cacheData != null) { 40 41 mTextView.setText(cacheData ); 42 } else {// 模拟网络请求数据 43 new Thread(new Runnable() { 44 @Override 45 public void run() { 46 SystemClock.sleep(1000); 47 aCache.put("newText", "保存3秒", 3);//间数据放到缓存中,保存时间是2秒 48 mHandler.sendEmptyMessage(1); 49 mHandler.sendEmptyMessageDelayed(2, 1000);//验证在保存转态 50 mHandler.sendEmptyMessageDelayed(3, 4000);//验证不在保存转态 51 } 52 }).start(); 53 54 } 55 56 } 57 58 private void initAcache() { 59 aCache = ACache.get(this);// 默认选择的路径是new File(context.getCacheDir(),// "ACache") 60 // String path = getExternalCacheDir().getAbsolutePath(); 61 // aCache = ACache.get(new File(path));//设置存储路径用于手动清空缓存使用, 62 } 63 64 }