├── .gitignore ├── AsimpleCacheDemo ├── .classpath ├── .project ├── .settings │ ├── org.eclipse.core.resources.prefs │ └── org.eclipse.jdt.core.prefs ├── ASimpleCache │ └── org │ │ └── afinal │ │ └── simplecache │ │ └── ACache.java ├── AndroidManifest.xml ├── bin │ └── AndroidManifest.xml ├── gen │ └── com │ │ └── yangfuhai │ │ └── asimplecachedemo │ │ ├── BuildConfig.java │ │ └── R.java ├── ic_launcher-web.png ├── proguard-project.txt ├── project.properties ├── res │ ├── drawable │ │ ├── ic_launcher.png │ │ └── img_test.png │ ├── layout │ │ ├── activity_about.xml │ │ ├── activity_main.xml │ │ ├── activity_save_bitmap.xml │ │ ├── activity_save_drawable.xml │ │ ├── activity_save_file.xml │ │ ├── activity_save_jsonarray.xml │ │ ├── activity_save_jsonobject.xml │ │ ├── activity_save_object.xml │ │ └── activity_save_string.xml │ ├── menu │ │ └── activity_save_jsonarray.xml │ └── values │ │ ├── strings.xml │ │ └── styles.xml └── src │ └── com │ └── yangfuhai │ └── asimplecachedemo │ ├── AboutActivity.java │ ├── MainActivity.java │ ├── SaveBitmapActivity.java │ ├── SaveDrawableActivity.java │ ├── SaveJsonArrayActivity.java │ ├── SaveJsonObjectActivity.java │ ├── SaveMediaActivity.java │ ├── SaveObjectActivity.java │ ├── SaveStringActivity.java │ └── beans │ └── UserBean.java ├── LICENSE ├── README.md └── source └── src └── org └── afinal └── simplecache └── ACache.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Package Files # 4 | *.jar 5 | *.war 6 | *.ear 7 | -------------------------------------------------------------------------------- /AsimpleCacheDemo/.classpath: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <classpath> 3 | <classpathentry kind="src" path="ASimpleCache"/> 4 | <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> 5 | <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> 6 | <classpathentry kind="src" path="src"/> 7 | <classpathentry kind="src" path="gen"/> 8 | <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/> 9 | <classpathentry kind="output" path="bin/classes"/> 10 | </classpath> 11 | -------------------------------------------------------------------------------- /AsimpleCacheDemo/.project: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <projectDescription> 3 | <name>AsimpleCacheDemo</name> 4 | <comment></comment> 5 | <projects> 6 | </projects> 7 | <buildSpec> 8 | <buildCommand> 9 | <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> 10 | <arguments> 11 | </arguments> 12 | </buildCommand> 13 | <buildCommand> 14 | <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> 15 | <arguments> 16 | </arguments> 17 | </buildCommand> 18 | <buildCommand> 19 | <name>org.eclipse.jdt.core.javabuilder</name> 20 | <arguments> 21 | </arguments> 22 | </buildCommand> 23 | <buildCommand> 24 | <name>com.android.ide.eclipse.adt.ApkBuilder</name> 25 | <arguments> 26 | </arguments> 27 | </buildCommand> 28 | </buildSpec> 29 | <natures> 30 | <nature>com.android.ide.eclipse.adt.AndroidNature</nature> 31 | <nature>org.eclipse.jdt.core.javanature</nature> 32 | </natures> 33 | </projectDescription> 34 | -------------------------------------------------------------------------------- /AsimpleCacheDemo/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding/<project>=UTF-8 3 | -------------------------------------------------------------------------------- /AsimpleCacheDemo/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 3 | org.eclipse.jdt.core.compiler.compliance=1.6 4 | org.eclipse.jdt.core.compiler.source=1.6 5 | -------------------------------------------------------------------------------- /AsimpleCacheDemo/ASimpleCache/org/afinal/simplecache/ACache.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2013, Michael Yang 杨福海 (www.yangfuhai.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.afinal.simplecache; 17 | 18 | import java.io.BufferedReader; 19 | import java.io.BufferedWriter; 20 | import java.io.ByteArrayInputStream; 21 | import java.io.ByteArrayOutputStream; 22 | import java.io.File; 23 | import java.io.FileInputStream; 24 | import java.io.FileNotFoundException; 25 | import java.io.FileOutputStream; 26 | import java.io.FileReader; 27 | import java.io.FileWriter; 28 | import java.io.IOException; 29 | import java.io.InputStream; 30 | import java.io.ObjectInputStream; 31 | import java.io.ObjectOutputStream; 32 | import java.io.OutputStream; 33 | import java.io.RandomAccessFile; 34 | import java.io.Serializable; 35 | import java.util.Collections; 36 | import java.util.HashMap; 37 | import java.util.Map; 38 | import java.util.Map.Entry; 39 | import java.util.Set; 40 | import java.util.concurrent.atomic.AtomicInteger; 41 | import java.util.concurrent.atomic.AtomicLong; 42 | 43 | import org.json.JSONArray; 44 | import org.json.JSONObject; 45 | 46 | import android.content.Context; 47 | import android.graphics.Bitmap; 48 | import android.graphics.BitmapFactory; 49 | import android.graphics.Canvas; 50 | import android.graphics.PixelFormat; 51 | import android.graphics.drawable.BitmapDrawable; 52 | import android.graphics.drawable.Drawable; 53 | 54 | /** 55 | * @author Michael Yang(www.yangfuhai.com) update at 2013.08.07 56 | */ 57 | public class ACache { 58 | public static final int TIME_HOUR = 60 * 60; 59 | public static final int TIME_DAY = TIME_HOUR * 24; 60 | private static final int MAX_SIZE = 1000 * 1000 * 50; // 50 mb 61 | private static final int MAX_COUNT = Integer.MAX_VALUE; // 不限制存放数据的数量 62 | private static Map<String, ACache> mInstanceMap = new HashMap<String, ACache>(); 63 | private ACacheManager mCache; 64 | 65 | public static ACache get(Context ctx) { 66 | return get(ctx, "ACache"); 67 | } 68 | 69 | public static ACache get(Context ctx, String cacheName) { 70 | File f = new File(ctx.getCacheDir(), cacheName); 71 | return get(f, MAX_SIZE, MAX_COUNT); 72 | } 73 | 74 | public static ACache get(File cacheDir) { 75 | return get(cacheDir, MAX_SIZE, MAX_COUNT); 76 | } 77 | 78 | public static ACache get(Context ctx, long max_zise, int max_count) { 79 | File f = new File(ctx.getCacheDir(), "ACache"); 80 | return get(f, max_zise, max_count); 81 | } 82 | 83 | public static ACache get(File cacheDir, long max_zise, int max_count) { 84 | ACache manager = mInstanceMap.get(cacheDir.getAbsoluteFile() + myPid()); 85 | if (manager == null) { 86 | manager = new ACache(cacheDir, max_zise, max_count); 87 | mInstanceMap.put(cacheDir.getAbsolutePath() + myPid(), manager); 88 | } 89 | return manager; 90 | } 91 | 92 | private static String myPid() { 93 | return "_" + android.os.Process.myPid(); 94 | } 95 | 96 | private ACache(File cacheDir, long max_size, int max_count) { 97 | if (!cacheDir.exists() && !cacheDir.mkdirs()) { 98 | throw new RuntimeException("can't make dirs in " + cacheDir.getAbsolutePath()); 99 | } 100 | mCache = new ACacheManager(cacheDir, max_size, max_count); 101 | } 102 | 103 | /** 104 | * Provides a means to save a cached file before the data are available. 105 | * Since writing about the file is complete, and its close method is called, 106 | * its contents will be registered in the cache. Example of use: 107 | * 108 | * ACache cache = new ACache(this) try { OutputStream stream = 109 | * cache.put("myFileName") stream.write("some bytes".getBytes()); // now 110 | * update cache! stream.close(); } catch(FileNotFoundException e){ 111 | * e.printStackTrace() } 112 | */ 113 | class xFileOutputStream extends FileOutputStream { 114 | File file; 115 | 116 | public xFileOutputStream(File file) throws FileNotFoundException { 117 | super(file); 118 | this.file = file; 119 | } 120 | 121 | public void close() throws IOException { 122 | super.close(); 123 | mCache.put(file); 124 | } 125 | } 126 | 127 | // ======================================= 128 | // ============ String数据 读写 ============== 129 | // ======================================= 130 | /** 131 | * 保存 String数据 到 缓存中 132 | * 133 | * @param key 134 | * 保存的key 135 | * @param value 136 | * 保存的String数据 137 | */ 138 | public void put(String key, String value) { 139 | File file = mCache.newFile(key); 140 | BufferedWriter out = null; 141 | try { 142 | out = new BufferedWriter(new FileWriter(file), 1024); 143 | out.write(value); 144 | } catch (IOException e) { 145 | e.printStackTrace(); 146 | } finally { 147 | if (out != null) { 148 | try { 149 | out.flush(); 150 | out.close(); 151 | } catch (IOException e) { 152 | e.printStackTrace(); 153 | } 154 | } 155 | mCache.put(file); 156 | } 157 | } 158 | 159 | /** 160 | * 保存 String数据 到 缓存中 161 | * 162 | * @param key 163 | * 保存的key 164 | * @param value 165 | * 保存的String数据 166 | * @param saveTime 167 | * 保存的时间,单位:秒 168 | */ 169 | public void put(String key, String value, int saveTime) { 170 | put(key, Utils.newStringWithDateInfo(saveTime, value)); 171 | } 172 | 173 | /** 174 | * 读取 String数据 175 | * 176 | * @param key 177 | * @return String 数据 178 | */ 179 | public String getAsString(String key) { 180 | File file = mCache.get(key); 181 | if (!file.exists()) 182 | return null; 183 | boolean removeFile = false; 184 | BufferedReader in = null; 185 | try { 186 | in = new BufferedReader(new FileReader(file)); 187 | String readString = ""; 188 | String currentLine; 189 | while ((currentLine = in.readLine()) != null) { 190 | readString += currentLine; 191 | } 192 | if (!Utils.isDue(readString)) { 193 | return Utils.clearDateInfo(readString); 194 | } else { 195 | removeFile = true; 196 | return null; 197 | } 198 | } catch (IOException e) { 199 | e.printStackTrace(); 200 | return null; 201 | } finally { 202 | if (in != null) { 203 | try { 204 | in.close(); 205 | } catch (IOException e) { 206 | e.printStackTrace(); 207 | } 208 | } 209 | if (removeFile) 210 | remove(key); 211 | } 212 | } 213 | 214 | // ======================================= 215 | // ============= JSONObject 数据 读写 ============== 216 | // ======================================= 217 | /** 218 | * 保存 JSONObject数据 到 缓存中 219 | * 220 | * @param key 221 | * 保存的key 222 | * @param value 223 | * 保存的JSON数据 224 | */ 225 | public void put(String key, JSONObject value) { 226 | put(key, value.toString()); 227 | } 228 | 229 | /** 230 | * 保存 JSONObject数据 到 缓存中 231 | * 232 | * @param key 233 | * 保存的key 234 | * @param value 235 | * 保存的JSONObject数据 236 | * @param saveTime 237 | * 保存的时间,单位:秒 238 | */ 239 | public void put(String key, JSONObject value, int saveTime) { 240 | put(key, value.toString(), saveTime); 241 | } 242 | 243 | /** 244 | * 读取JSONObject数据 245 | * 246 | * @param key 247 | * @return JSONObject数据 248 | */ 249 | public JSONObject getAsJSONObject(String key) { 250 | String JSONString = getAsString(key); 251 | try { 252 | JSONObject obj = new JSONObject(JSONString); 253 | return obj; 254 | } catch (Exception e) { 255 | e.printStackTrace(); 256 | return null; 257 | } 258 | } 259 | 260 | // ======================================= 261 | // ============ JSONArray 数据 读写 ============= 262 | // ======================================= 263 | /** 264 | * 保存 JSONArray数据 到 缓存中 265 | * 266 | * @param key 267 | * 保存的key 268 | * @param value 269 | * 保存的JSONArray数据 270 | */ 271 | public void put(String key, JSONArray value) { 272 | put(key, value.toString()); 273 | } 274 | 275 | /** 276 | * 保存 JSONArray数据 到 缓存中 277 | * 278 | * @param key 279 | * 保存的key 280 | * @param value 281 | * 保存的JSONArray数据 282 | * @param saveTime 283 | * 保存的时间,单位:秒 284 | */ 285 | public void put(String key, JSONArray value, int saveTime) { 286 | put(key, value.toString(), saveTime); 287 | } 288 | 289 | /** 290 | * 读取JSONArray数据 291 | * 292 | * @param key 293 | * @return JSONArray数据 294 | */ 295 | public JSONArray getAsJSONArray(String key) { 296 | String JSONString = getAsString(key); 297 | try { 298 | JSONArray obj = new JSONArray(JSONString); 299 | return obj; 300 | } catch (Exception e) { 301 | e.printStackTrace(); 302 | return null; 303 | } 304 | } 305 | 306 | // ======================================= 307 | // ============== byte 数据 读写 ============= 308 | // ======================================= 309 | /** 310 | * 保存 byte数据 到 缓存中 311 | * 312 | * @param key 313 | * 保存的key 314 | * @param value 315 | * 保存的数据 316 | */ 317 | public void put(String key, byte[] value) { 318 | File file = mCache.newFile(key); 319 | FileOutputStream out = null; 320 | try { 321 | out = new FileOutputStream(file); 322 | out.write(value); 323 | } catch (Exception e) { 324 | e.printStackTrace(); 325 | } finally { 326 | if (out != null) { 327 | try { 328 | out.flush(); 329 | out.close(); 330 | } catch (IOException e) { 331 | e.printStackTrace(); 332 | } 333 | } 334 | mCache.put(file); 335 | } 336 | } 337 | 338 | /** 339 | * Cache for a stream 340 | * 341 | * @param key 342 | * the file name. 343 | * @return OutputStream stream for writing data. 344 | * @throws FileNotFoundException 345 | * if the file can not be created. 346 | */ 347 | public OutputStream put(String key) throws FileNotFoundException { 348 | return new xFileOutputStream(mCache.newFile(key)); 349 | } 350 | 351 | /** 352 | * 353 | * @param key 354 | * the file name. 355 | * @return (InputStream or null) stream previously saved in cache. 356 | * @throws FileNotFoundException 357 | * if the file can not be opened 358 | */ 359 | public InputStream get(String key) throws FileNotFoundException { 360 | File file = mCache.get(key); 361 | if (!file.exists()) 362 | return null; 363 | return new FileInputStream(file); 364 | } 365 | 366 | /** 367 | * 保存 byte数据 到 缓存中 368 | * 369 | * @param key 370 | * 保存的key 371 | * @param value 372 | * 保存的数据 373 | * @param saveTime 374 | * 保存的时间,单位:秒 375 | */ 376 | public void put(String key, byte[] value, int saveTime) { 377 | put(key, Utils.newByteArrayWithDateInfo(saveTime, value)); 378 | } 379 | 380 | /** 381 | * 获取 byte 数据 382 | * 383 | * @param key 384 | * @return byte 数据 385 | */ 386 | public byte[] getAsBinary(String key) { 387 | RandomAccessFile RAFile = null; 388 | boolean removeFile = false; 389 | try { 390 | File file = mCache.get(key); 391 | if (!file.exists()) 392 | return null; 393 | RAFile = new RandomAccessFile(file, "r"); 394 | byte[] byteArray = new byte[(int) RAFile.length()]; 395 | RAFile.read(byteArray); 396 | if (!Utils.isDue(byteArray)) { 397 | return Utils.clearDateInfo(byteArray); 398 | } else { 399 | removeFile = true; 400 | return null; 401 | } 402 | } catch (Exception e) { 403 | e.printStackTrace(); 404 | return null; 405 | } finally { 406 | if (RAFile != null) { 407 | try { 408 | RAFile.close(); 409 | } catch (IOException e) { 410 | e.printStackTrace(); 411 | } 412 | } 413 | if (removeFile) 414 | remove(key); 415 | } 416 | } 417 | 418 | // ======================================= 419 | // ============= 序列化 数据 读写 =============== 420 | // ======================================= 421 | /** 422 | * 保存 Serializable数据 到 缓存中 423 | * 424 | * @param key 425 | * 保存的key 426 | * @param value 427 | * 保存的value 428 | */ 429 | public void put(String key, Serializable value) { 430 | put(key, value, -1); 431 | } 432 | 433 | /** 434 | * 保存 Serializable数据到 缓存中 435 | * 436 | * @param key 437 | * 保存的key 438 | * @param value 439 | * 保存的value 440 | * @param saveTime 441 | * 保存的时间,单位:秒 442 | */ 443 | public void put(String key, Serializable value, int saveTime) { 444 | ByteArrayOutputStream baos = null; 445 | ObjectOutputStream oos = null; 446 | try { 447 | baos = new ByteArrayOutputStream(); 448 | oos = new ObjectOutputStream(baos); 449 | oos.writeObject(value); 450 | byte[] data = baos.toByteArray(); 451 | if (saveTime != -1) { 452 | put(key, data, saveTime); 453 | } else { 454 | put(key, data); 455 | } 456 | } catch (Exception e) { 457 | e.printStackTrace(); 458 | } finally { 459 | try { 460 | oos.close(); 461 | } catch (IOException e) { 462 | } 463 | } 464 | } 465 | 466 | /** 467 | * 读取 Serializable数据 468 | * 469 | * @param key 470 | * @return Serializable 数据 471 | */ 472 | public Object getAsObject(String key) { 473 | byte[] data = getAsBinary(key); 474 | if (data != null) { 475 | ByteArrayInputStream bais = null; 476 | ObjectInputStream ois = null; 477 | try { 478 | bais = new ByteArrayInputStream(data); 479 | ois = new ObjectInputStream(bais); 480 | Object reObject = ois.readObject(); 481 | return reObject; 482 | } catch (Exception e) { 483 | e.printStackTrace(); 484 | return null; 485 | } finally { 486 | try { 487 | if (bais != null) 488 | bais.close(); 489 | } catch (IOException e) { 490 | e.printStackTrace(); 491 | } 492 | try { 493 | if (ois != null) 494 | ois.close(); 495 | } catch (IOException e) { 496 | e.printStackTrace(); 497 | } 498 | } 499 | } 500 | return null; 501 | 502 | } 503 | 504 | // ======================================= 505 | // ============== bitmap 数据 读写 ============= 506 | // ======================================= 507 | /** 508 | * 保存 bitmap 到 缓存中 509 | * 510 | * @param key 511 | * 保存的key 512 | * @param value 513 | * 保存的bitmap数据 514 | */ 515 | public void put(String key, Bitmap value) { 516 | put(key, Utils.Bitmap2Bytes(value)); 517 | } 518 | 519 | /** 520 | * 保存 bitmap 到 缓存中 521 | * 522 | * @param key 523 | * 保存的key 524 | * @param value 525 | * 保存的 bitmap 数据 526 | * @param saveTime 527 | * 保存的时间,单位:秒 528 | */ 529 | public void put(String key, Bitmap value, int saveTime) { 530 | put(key, Utils.Bitmap2Bytes(value), saveTime); 531 | } 532 | 533 | /** 534 | * 读取 bitmap 数据 535 | * 536 | * @param key 537 | * @return bitmap 数据 538 | */ 539 | public Bitmap getAsBitmap(String key) { 540 | if (getAsBinary(key) == null) { 541 | return null; 542 | } 543 | return Utils.Bytes2Bimap(getAsBinary(key)); 544 | } 545 | 546 | // ======================================= 547 | // ============= drawable 数据 读写 ============= 548 | // ======================================= 549 | /** 550 | * 保存 drawable 到 缓存中 551 | * 552 | * @param key 553 | * 保存的key 554 | * @param value 555 | * 保存的drawable数据 556 | */ 557 | public void put(String key, Drawable value) { 558 | put(key, Utils.drawable2Bitmap(value)); 559 | } 560 | 561 | /** 562 | * 保存 drawable 到 缓存中 563 | * 564 | * @param key 565 | * 保存的key 566 | * @param value 567 | * 保存的 drawable 数据 568 | * @param saveTime 569 | * 保存的时间,单位:秒 570 | */ 571 | public void put(String key, Drawable value, int saveTime) { 572 | put(key, Utils.drawable2Bitmap(value), saveTime); 573 | } 574 | 575 | /** 576 | * 读取 Drawable 数据 577 | * 578 | * @param key 579 | * @return Drawable 数据 580 | */ 581 | public Drawable getAsDrawable(String key) { 582 | if (getAsBinary(key) == null) { 583 | return null; 584 | } 585 | return Utils.bitmap2Drawable(Utils.Bytes2Bimap(getAsBinary(key))); 586 | } 587 | 588 | /** 589 | * 获取缓存文件 590 | * 591 | * @param key 592 | * @return value 缓存的文件 593 | */ 594 | public File file(String key) { 595 | File f = mCache.newFile(key); 596 | if (f.exists()) 597 | return f; 598 | return null; 599 | } 600 | 601 | /** 602 | * 移除某个key 603 | * 604 | * @param key 605 | * @return 是否移除成功 606 | */ 607 | public boolean remove(String key) { 608 | return mCache.remove(key); 609 | } 610 | 611 | /** 612 | * 清除所有数据 613 | */ 614 | public void clear() { 615 | mCache.clear(); 616 | } 617 | 618 | /** 619 | * @title 缓存管理器 620 | * @author 杨福海(michael) www.yangfuhai.com 621 | * @version 1.0 622 | */ 623 | public class ACacheManager { 624 | private final AtomicLong cacheSize; 625 | private final AtomicInteger cacheCount; 626 | private final long sizeLimit; 627 | private final int countLimit; 628 | private final Map<File, Long> lastUsageDates = Collections.synchronizedMap(new HashMap<File, Long>()); 629 | protected File cacheDir; 630 | 631 | private ACacheManager(File cacheDir, long sizeLimit, int countLimit) { 632 | this.cacheDir = cacheDir; 633 | this.sizeLimit = sizeLimit; 634 | this.countLimit = countLimit; 635 | cacheSize = new AtomicLong(); 636 | cacheCount = new AtomicInteger(); 637 | calculateCacheSizeAndCacheCount(); 638 | } 639 | 640 | /** 641 | * 计算 cacheSize和cacheCount 642 | */ 643 | private void calculateCacheSizeAndCacheCount() { 644 | new Thread(new Runnable() { 645 | @Override 646 | public void run() { 647 | int size = 0; 648 | int count = 0; 649 | File[] cachedFiles = cacheDir.listFiles(); 650 | if (cachedFiles != null) { 651 | for (File cachedFile : cachedFiles) { 652 | size += calculateSize(cachedFile); 653 | count += 1; 654 | lastUsageDates.put(cachedFile, cachedFile.lastModified()); 655 | } 656 | cacheSize.set(size); 657 | cacheCount.set(count); 658 | } 659 | } 660 | }).start(); 661 | } 662 | 663 | private void put(File file) { 664 | int curCacheCount = cacheCount.get(); 665 | while (curCacheCount + 1 > countLimit) { 666 | long freedSize = removeNext(); 667 | cacheSize.addAndGet(-freedSize); 668 | 669 | curCacheCount = cacheCount.addAndGet(-1); 670 | } 671 | cacheCount.addAndGet(1); 672 | 673 | long valueSize = calculateSize(file); 674 | long curCacheSize = cacheSize.get(); 675 | while (curCacheSize + valueSize > sizeLimit) { 676 | long freedSize = removeNext(); 677 | curCacheSize = cacheSize.addAndGet(-freedSize); 678 | } 679 | cacheSize.addAndGet(valueSize); 680 | 681 | Long currentTime = System.currentTimeMillis(); 682 | file.setLastModified(currentTime); 683 | lastUsageDates.put(file, currentTime); 684 | } 685 | 686 | private File get(String key) { 687 | File file = newFile(key); 688 | Long currentTime = System.currentTimeMillis(); 689 | file.setLastModified(currentTime); 690 | lastUsageDates.put(file, currentTime); 691 | 692 | return file; 693 | } 694 | 695 | private File newFile(String key) { 696 | return new File(cacheDir, key.hashCode() + ""); 697 | } 698 | 699 | private boolean remove(String key) { 700 | File image = get(key); 701 | return image.delete(); 702 | } 703 | 704 | private void clear() { 705 | lastUsageDates.clear(); 706 | cacheSize.set(0); 707 | File[] files = cacheDir.listFiles(); 708 | if (files != null) { 709 | for (File f : files) { 710 | f.delete(); 711 | } 712 | } 713 | } 714 | 715 | /** 716 | * 移除旧的文件 717 | * 718 | * @return 719 | */ 720 | private long removeNext() { 721 | if (lastUsageDates.isEmpty()) { 722 | return 0; 723 | } 724 | 725 | Long oldestUsage = null; 726 | File mostLongUsedFile = null; 727 | Set<Entry<File, Long>> entries = lastUsageDates.entrySet(); 728 | synchronized (lastUsageDates) { 729 | for (Entry<File, Long> entry : entries) { 730 | if (mostLongUsedFile == null) { 731 | mostLongUsedFile = entry.getKey(); 732 | oldestUsage = entry.getValue(); 733 | } else { 734 | Long lastValueUsage = entry.getValue(); 735 | if (lastValueUsage < oldestUsage) { 736 | oldestUsage = lastValueUsage; 737 | mostLongUsedFile = entry.getKey(); 738 | } 739 | } 740 | } 741 | } 742 | 743 | long fileSize = calculateSize(mostLongUsedFile); 744 | if (mostLongUsedFile.delete()) { 745 | lastUsageDates.remove(mostLongUsedFile); 746 | } 747 | return fileSize; 748 | } 749 | 750 | private long calculateSize(File file) { 751 | return file.length(); 752 | } 753 | } 754 | 755 | /** 756 | * @title 时间计算工具类 757 | * @author 杨福海(michael) www.yangfuhai.com 758 | * @version 1.0 759 | */ 760 | private static class Utils { 761 | 762 | /** 763 | * 判断缓存的String数据是否到期 764 | * 765 | * @param str 766 | * @return true:到期了 false:还没有到期 767 | */ 768 | private static boolean isDue(String str) { 769 | return isDue(str.getBytes()); 770 | } 771 | 772 | /** 773 | * 判断缓存的byte数据是否到期 774 | * 775 | * @param data 776 | * @return true:到期了 false:还没有到期 777 | */ 778 | private static boolean isDue(byte[] data) { 779 | String[] strs = getDateInfoFromDate(data); 780 | if (strs != null && strs.length == 2) { 781 | String saveTimeStr = strs[0]; 782 | while (saveTimeStr.startsWith("0")) { 783 | saveTimeStr = saveTimeStr.substring(1, saveTimeStr.length()); 784 | } 785 | long saveTime = Long.valueOf(saveTimeStr); 786 | long deleteAfter = Long.valueOf(strs[1]); 787 | if (System.currentTimeMillis() > saveTime + deleteAfter * 1000) { 788 | return true; 789 | } 790 | } 791 | return false; 792 | } 793 | 794 | private static String newStringWithDateInfo(int second, String strInfo) { 795 | return createDateInfo(second) + strInfo; 796 | } 797 | 798 | private static byte[] newByteArrayWithDateInfo(int second, byte[] data2) { 799 | byte[] data1 = createDateInfo(second).getBytes(); 800 | byte[] retdata = new byte[data1.length + data2.length]; 801 | System.arraycopy(data1, 0, retdata, 0, data1.length); 802 | System.arraycopy(data2, 0, retdata, data1.length, data2.length); 803 | return retdata; 804 | } 805 | 806 | private static String clearDateInfo(String strInfo) { 807 | if (strInfo != null && hasDateInfo(strInfo.getBytes())) { 808 | strInfo = strInfo.substring(strInfo.indexOf(mSeparator) + 1, strInfo.length()); 809 | } 810 | return strInfo; 811 | } 812 | 813 | private static byte[] clearDateInfo(byte[] data) { 814 | if (hasDateInfo(data)) { 815 | return copyOfRange(data, indexOf(data, mSeparator) + 1, data.length); 816 | } 817 | return data; 818 | } 819 | 820 | private static boolean hasDateInfo(byte[] data) { 821 | return data != null && data.length > 15 && data[13] == '-' && indexOf(data, mSeparator) > 14; 822 | } 823 | 824 | private static String[] getDateInfoFromDate(byte[] data) { 825 | if (hasDateInfo(data)) { 826 | String saveDate = new String(copyOfRange(data, 0, 13)); 827 | String deleteAfter = new String(copyOfRange(data, 14, indexOf(data, mSeparator))); 828 | return new String[] { saveDate, deleteAfter }; 829 | } 830 | return null; 831 | } 832 | 833 | private static int indexOf(byte[] data, char c) { 834 | for (int i = 0; i < data.length; i++) { 835 | if (data[i] == c) { 836 | return i; 837 | } 838 | } 839 | return -1; 840 | } 841 | 842 | private static byte[] copyOfRange(byte[] original, int from, int to) { 843 | int newLength = to - from; 844 | if (newLength < 0) 845 | throw new IllegalArgumentException(from + " > " + to); 846 | byte[] copy = new byte[newLength]; 847 | System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength)); 848 | return copy; 849 | } 850 | 851 | private static final char mSeparator = ' '; 852 | 853 | private static String createDateInfo(int second) { 854 | String currentTime = System.currentTimeMillis() + ""; 855 | while (currentTime.length() < 13) { 856 | currentTime = "0" + currentTime; 857 | } 858 | return currentTime + "-" + second + mSeparator; 859 | } 860 | 861 | /* 862 | * Bitmap → byte[] 863 | */ 864 | private static byte[] Bitmap2Bytes(Bitmap bm) { 865 | if (bm == null) { 866 | return null; 867 | } 868 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 869 | bm.compress(Bitmap.CompressFormat.PNG, 100, baos); 870 | return baos.toByteArray(); 871 | } 872 | 873 | /* 874 | * byte[] → Bitmap 875 | */ 876 | private static Bitmap Bytes2Bimap(byte[] b) { 877 | if (b.length == 0) { 878 | return null; 879 | } 880 | return BitmapFactory.decodeByteArray(b, 0, b.length); 881 | } 882 | 883 | /* 884 | * Drawable → Bitmap 885 | */ 886 | private static Bitmap drawable2Bitmap(Drawable drawable) { 887 | if (drawable == null) { 888 | return null; 889 | } 890 | // 取 drawable 的长宽 891 | int w = drawable.getIntrinsicWidth(); 892 | int h = drawable.getIntrinsicHeight(); 893 | // 取 drawable 的颜色格式 894 | Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; 895 | // 建立对应 bitmap 896 | Bitmap bitmap = Bitmap.createBitmap(w, h, config); 897 | // 建立对应 bitmap 的画布 898 | Canvas canvas = new Canvas(bitmap); 899 | drawable.setBounds(0, 0, w, h); 900 | // 把 drawable 内容画到画布中 901 | drawable.draw(canvas); 902 | return bitmap; 903 | } 904 | 905 | /* 906 | * Bitmap → Drawable 907 | */ 908 | @SuppressWarnings("deprecation") 909 | private static Drawable bitmap2Drawable(Bitmap bm) { 910 | if (bm == null) { 911 | return null; 912 | } 913 | BitmapDrawable bd=new BitmapDrawable(bm); 914 | bd.setTargetDensity(bm.getDensity()); 915 | return new BitmapDrawable(bm); 916 | } 917 | } 918 | 919 | } 920 | -------------------------------------------------------------------------------- /AsimpleCacheDemo/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <manifest xmlns:android="http://schemas.android.com/apk/res/android" 3 | package="com.yangfuhai.asimplecachedemo" 4 | android:versionCode="1" 5 | android:versionName="1.0" > 6 | 7 | <uses-permission android:name="android.permission.INTERNET"></uses-permission> 8 | 9 | <uses-sdk 10 | android:minSdkVersion="4" 11 | android:targetSdkVersion="16" /> 12 | 13 | <application 14 | android:allowBackup="true" 15 | android:icon="@drawable/ic_launcher" 16 | android:label="@string/app_name" 17 | android:theme="@style/AppTheme" > 18 | <activity 19 | android:name="com.yangfuhai.asimplecachedemo.MainActivity" 20 | android:label="@string/app_name" > 21 | <intent-filter> 22 | <action android:name="android.intent.action.MAIN" /> 23 | 24 | <category android:name="android.intent.category.LAUNCHER" /> 25 | </intent-filter> 26 | </activity> 27 | <activity android:name="com.yangfuhai.asimplecachedemo.AboutActivity" /> 28 | <activity android:name="com.yangfuhai.asimplecachedemo.SaveBitmapActivity" /> 29 | <activity android:name="com.yangfuhai.asimplecachedemo.SaveJsonObjectActivity" /> 30 | <activity android:name="com.yangfuhai.asimplecachedemo.SaveObjectActivity" /> 31 | <activity android:name="com.yangfuhai.asimplecachedemo.SaveStringActivity" /> 32 | <activity android:name="com.yangfuhai.asimplecachedemo.SaveMediaActivity" /> 33 | <activity 34 | android:name="com.yangfuhai.asimplecachedemo.SaveDrawableActivity" 35 | android:label="@string/title_activity_save_drawable" > 36 | </activity> 37 | <activity 38 | android:name="com.yangfuhai.asimplecachedemo.SaveJsonArrayActivity" 39 | android:label="@string/title_activity_save_json_array" > 40 | </activity> 41 | </application> 42 | 43 | </manifest> -------------------------------------------------------------------------------- /AsimpleCacheDemo/bin/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <manifest xmlns:android="http://schemas.android.com/apk/res/android" 3 | package="com.yangfuhai.asimplecachedemo" 4 | android:versionCode="1" 5 | android:versionName="1.0" > 6 | 7 | <uses-permission android:name="android.permission.INTERNET"></uses-permission> 8 | 9 | <uses-sdk 10 | android:minSdkVersion="4" 11 | android:targetSdkVersion="16" /> 12 | 13 | <application 14 | android:allowBackup="true" 15 | android:icon="@drawable/ic_launcher" 16 | android:label="@string/app_name" 17 | android:theme="@style/AppTheme" > 18 | <activity 19 | android:name="com.yangfuhai.asimplecachedemo.MainActivity" 20 | android:label="@string/app_name" > 21 | <intent-filter> 22 | <action android:name="android.intent.action.MAIN" /> 23 | 24 | <category android:name="android.intent.category.LAUNCHER" /> 25 | </intent-filter> 26 | </activity> 27 | <activity android:name="com.yangfuhai.asimplecachedemo.AboutActivity" /> 28 | <activity android:name="com.yangfuhai.asimplecachedemo.SaveBitmapActivity" /> 29 | <activity android:name="com.yangfuhai.asimplecachedemo.SaveJsonObjectActivity" /> 30 | <activity android:name="com.yangfuhai.asimplecachedemo.SaveObjectActivity" /> 31 | <activity android:name="com.yangfuhai.asimplecachedemo.SaveStringActivity" /> 32 | <activity android:name="com.yangfuhai.asimplecachedemo.SaveMediaActivity" /> 33 | <activity 34 | android:name="com.yangfuhai.asimplecachedemo.SaveDrawableActivity" 35 | android:label="@string/title_activity_save_drawable" > 36 | </activity> 37 | <activity 38 | android:name="com.yangfuhai.asimplecachedemo.SaveJsonArrayActivity" 39 | android:label="@string/title_activity_save_json_array" > 40 | </activity> 41 | </application> 42 | 43 | </manifest> -------------------------------------------------------------------------------- /AsimpleCacheDemo/gen/com/yangfuhai/asimplecachedemo/BuildConfig.java: -------------------------------------------------------------------------------- 1 | /** Automatically generated file. DO NOT MODIFY */ 2 | package com.yangfuhai.asimplecachedemo; 3 | 4 | public final class BuildConfig { 5 | public final static boolean DEBUG = true; 6 | } -------------------------------------------------------------------------------- /AsimpleCacheDemo/gen/com/yangfuhai/asimplecachedemo/R.java: -------------------------------------------------------------------------------- 1 | /* AUTO-GENERATED FILE. DO NOT MODIFY. 2 | * 3 | * This class was automatically generated by the 4 | * aapt tool from the resource data it found. It 5 | * should not be modified by hand. 6 | */ 7 | 8 | package com.yangfuhai.asimplecachedemo; 9 | 10 | public final class R { 11 | public static final class attr { 12 | } 13 | public static final class drawable { 14 | public static final int ic_launcher=0x7f020000; 15 | public static final int img_test=0x7f020001; 16 | } 17 | public static final class id { 18 | public static final int btn_about=0x7f070008; 19 | public static final int btn_save_bitmap=0x7f070004; 20 | public static final int btn_save_drawable=0x7f070006; 21 | public static final int btn_save_file=0x7f070005; 22 | public static final int btn_save_jsonarray=0x7f070003; 23 | public static final int btn_save_jsonobject=0x7f070002; 24 | public static final int btn_save_object=0x7f070007; 25 | public static final int btn_save_string=0x7f070001; 26 | public static final int et_string_input=0x7f070012; 27 | public static final int iv_bitmap_res=0x7f070009; 28 | public static final int iv_drawable_res=0x7f07000a; 29 | public static final int menu_settings=0x7f070014; 30 | public static final int text=0x7f07000b; 31 | public static final int textView1=0x7f070000; 32 | public static final int tv_jsonarray_original=0x7f07000c; 33 | public static final int tv_jsonarray_res=0x7f07000d; 34 | public static final int tv_jsonobject_original=0x7f07000e; 35 | public static final int tv_jsonobject_res=0x7f07000f; 36 | public static final int tv_object_original=0x7f070010; 37 | public static final int tv_object_res=0x7f070011; 38 | public static final int tv_string_res=0x7f070013; 39 | } 40 | public static final class layout { 41 | public static final int activity_about=0x7f030000; 42 | public static final int activity_main=0x7f030001; 43 | public static final int activity_save_bitmap=0x7f030002; 44 | public static final int activity_save_drawable=0x7f030003; 45 | public static final int activity_save_file=0x7f030004; 46 | public static final int activity_save_jsonarray=0x7f030005; 47 | public static final int activity_save_jsonobject=0x7f030006; 48 | public static final int activity_save_object=0x7f030007; 49 | public static final int activity_save_string=0x7f030008; 50 | } 51 | public static final class menu { 52 | public static final int activity_save_jsonarray=0x7f060000; 53 | } 54 | public static final class string { 55 | public static final int app_name=0x7f040000; 56 | public static final int hello_world=0x7f040001; 57 | public static final int menu_settings=0x7f040002; 58 | public static final int title_activity_save_drawable=0x7f040003; 59 | public static final int title_activity_save_json_array=0x7f040004; 60 | } 61 | public static final class style { 62 | /** 63 | Base application theme, dependent on API level. This theme is replaced 64 | by AppBaseTheme from res/values-vXX/styles.xml on newer devices. 65 | 66 | 67 | Theme customizations available in newer API levels can go in 68 | res/values-vXX/styles.xml, while customizations related to 69 | backward-compatibility can go here. 70 | 71 | */ 72 | public static final int AppBaseTheme=0x7f050000; 73 | /** Application theme. 74 | All customizations that are NOT specific to a particular API-level can go here. 75 | */ 76 | public static final int AppTheme=0x7f050001; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /AsimpleCacheDemo/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangfuhai/ASimpleCache/7935b04751aa57299cfb8b89e5b1e12a2d96e7cb/AsimpleCacheDemo/ic_launcher-web.png -------------------------------------------------------------------------------- /AsimpleCacheDemo/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /AsimpleCacheDemo/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-19 15 | -------------------------------------------------------------------------------- /AsimpleCacheDemo/res/drawable/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangfuhai/ASimpleCache/7935b04751aa57299cfb8b89e5b1e12a2d96e7cb/AsimpleCacheDemo/res/drawable/ic_launcher.png -------------------------------------------------------------------------------- /AsimpleCacheDemo/res/drawable/img_test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangfuhai/ASimpleCache/7935b04751aa57299cfb8b89e5b1e12a2d96e7cb/AsimpleCacheDemo/res/drawable/img_test.png -------------------------------------------------------------------------------- /AsimpleCacheDemo/res/layout/activity_about.xml: -------------------------------------------------------------------------------- 1 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 | xmlns:tools="http://schemas.android.com/tools" 3 | android:layout_width="match_parent" 4 | android:layout_height="match_parent" 5 | android:orientation="vertical" 6 | tools:context=".MainActivity" > 7 | 8 | <TextView 9 | android:id="@+id/textView1" 10 | android:layout_width="match_parent" 11 | android:layout_height="wrap_content" 12 | android:layout_centerHorizontal="true" 13 | android:layout_centerVertical="true" 14 | android:text="source:\n 15 | http://github.com/yangfuhai/ASimpleCache \n 16 | author:\n 17 | michael Yang " /> 18 | 19 | </LinearLayout> -------------------------------------------------------------------------------- /AsimpleCacheDemo/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 | xmlns:tools="http://schemas.android.com/tools" 3 | android:layout_width="match_parent" 4 | android:layout_height="match_parent" 5 | android:orientation="vertical" 6 | tools:context=".MainActivity" > 7 | 8 | <TextView 9 | android:id="@+id/textView1" 10 | android:layout_width="match_parent" 11 | android:layout_height="wrap_content" 12 | android:text="@string/hello_world" /> 13 | 14 | <Button 15 | android:id="@+id/btn_save_string" 16 | android:layout_width="match_parent" 17 | android:layout_height="wrap_content" 18 | android:onClick="string" 19 | android:text="String Cache" /> 20 | 21 | <Button 22 | android:id="@+id/btn_save_jsonobject" 23 | android:layout_width="match_parent" 24 | android:layout_height="wrap_content" 25 | android:onClick="jsonobject" 26 | android:text="JsonObject Cache" /> 27 | 28 | <Button 29 | android:id="@+id/btn_save_jsonarray" 30 | android:layout_width="match_parent" 31 | android:layout_height="wrap_content" 32 | android:onClick="jsonarray" 33 | android:text="JsonArray Cache" /> 34 | 35 | <Button 36 | android:id="@+id/btn_save_bitmap" 37 | android:layout_width="match_parent" 38 | android:layout_height="wrap_content" 39 | android:onClick="bitmap" 40 | android:text="Bitmap Cache" /> 41 | 42 | <Button 43 | android:id="@+id/btn_save_file" 44 | android:layout_width="match_parent" 45 | android:layout_height="wrap_content" 46 | android:onClick="media" 47 | android:text="Media Cache" /> 48 | 49 | <Button 50 | android:id="@+id/btn_save_drawable" 51 | android:layout_width="match_parent" 52 | android:layout_height="wrap_content" 53 | android:onClick="drawable" 54 | android:text="Drawable Cache" /> 55 | 56 | <Button 57 | android:id="@+id/btn_save_object" 58 | android:layout_width="match_parent" 59 | android:layout_height="wrap_content" 60 | android:onClick="object" 61 | android:text="Object Cache" /> 62 | 63 | <Button 64 | android:id="@+id/btn_about" 65 | android:layout_width="match_parent" 66 | android:layout_height="wrap_content" 67 | android:onClick="about" 68 | android:text="btn_about" /> 69 | 70 | </LinearLayout> -------------------------------------------------------------------------------- /AsimpleCacheDemo/res/layout/activity_save_bitmap.xml: -------------------------------------------------------------------------------- 1 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 | xmlns:tools="http://schemas.android.com/tools" 3 | android:layout_width="match_parent" 4 | android:layout_height="match_parent" 5 | android:gravity="center|top" 6 | android:orientation="vertical" 7 | tools:context=".MainActivity" > 8 | 9 | <Button 10 | android:layout_width="match_parent" 11 | android:layout_height="wrap_content" 12 | android:onClick="save" 13 | android:text="save" /> 14 | 15 | <Button 16 | android:layout_width="match_parent" 17 | android:layout_height="wrap_content" 18 | android:onClick="read" 19 | android:text="read" /> 20 | 21 | <Button 22 | android:layout_width="match_parent" 23 | android:layout_height="wrap_content" 24 | android:onClick="clear" 25 | android:text="clear this Bitmap" /> 26 | 27 | <ImageView 28 | android:layout_width="wrap_content" 29 | android:layout_height="wrap_content" 30 | android:layout_margin="5dp" 31 | android:contentDescription="@null" 32 | android:src="@drawable/img_test" /> 33 | 34 | <TextView 35 | android:layout_width="match_parent" 36 | android:layout_height="1dp" 37 | android:background="#E5E5E5" /> 38 | 39 | <ImageView 40 | android:id="@+id/iv_bitmap_res" 41 | android:layout_width="wrap_content" 42 | android:layout_height="wrap_content" 43 | android:layout_margin="5dp" 44 | android:contentDescription="@null" /> 45 | 46 | </LinearLayout> -------------------------------------------------------------------------------- /AsimpleCacheDemo/res/layout/activity_save_drawable.xml: -------------------------------------------------------------------------------- 1 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 | xmlns:tools="http://schemas.android.com/tools" 3 | android:layout_width="match_parent" 4 | android:layout_height="match_parent" 5 | android:gravity="center|top" 6 | android:orientation="vertical" 7 | tools:context=".MainActivity" > 8 | 9 | <Button 10 | android:layout_width="match_parent" 11 | android:layout_height="wrap_content" 12 | android:onClick="save" 13 | android:text="save" /> 14 | 15 | <Button 16 | android:layout_width="match_parent" 17 | android:layout_height="wrap_content" 18 | android:onClick="read" 19 | android:text="read" /> 20 | 21 | <Button 22 | android:layout_width="match_parent" 23 | android:layout_height="wrap_content" 24 | android:onClick="clear" 25 | android:text="clear this Drawable" /> 26 | 27 | <ImageView 28 | android:layout_width="wrap_content" 29 | android:layout_height="wrap_content" 30 | android:layout_margin="5dp" 31 | android:contentDescription="@null" 32 | android:src="@drawable/img_test" /> 33 | 34 | <TextView 35 | android:layout_width="match_parent" 36 | android:layout_height="1dp" 37 | android:background="#E5E5E5" /> 38 | 39 | <ImageView 40 | android:id="@+id/iv_drawable_res" 41 | android:layout_width="wrap_content" 42 | android:layout_height="wrap_content" 43 | android:layout_margin="5dp" 44 | android:contentDescription="@null" /> 45 | 46 | </LinearLayout> -------------------------------------------------------------------------------- /AsimpleCacheDemo/res/layout/activity_save_file.xml: -------------------------------------------------------------------------------- 1 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 | xmlns:tools="http://schemas.android.com/tools" 3 | android:layout_width="match_parent" 4 | android:layout_height="match_parent" 5 | android:gravity="center|top" 6 | android:orientation="vertical" 7 | tools:context=".MainActivity" > 8 | 9 | <Button 10 | android:layout_width="match_parent" 11 | android:layout_height="wrap_content" 12 | android:onClick="save" 13 | android:text="save" /> 14 | 15 | <Button 16 | android:layout_width="match_parent" 17 | android:layout_height="wrap_content" 18 | android:onClick="read" 19 | android:text="read" /> 20 | 21 | <Button 22 | android:layout_width="match_parent" 23 | android:layout_height="wrap_content" 24 | android:onClick="clear" 25 | android:text="clear this Bitmap" /> 26 | 27 | <TextView 28 | android:layout_width="match_parent" 29 | android:layout_height="wrap_content" 30 | android:background="#E5E5E5" 31 | android:id="@+id/text"/> 32 | 33 | </LinearLayout> -------------------------------------------------------------------------------- /AsimpleCacheDemo/res/layout/activity_save_jsonarray.xml: -------------------------------------------------------------------------------- 1 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 | xmlns:tools="http://schemas.android.com/tools" 3 | android:layout_width="match_parent" 4 | android:layout_height="match_parent" 5 | android:gravity="center|top" 6 | android:orientation="vertical" > 7 | 8 | <Button 9 | android:layout_width="match_parent" 10 | android:layout_height="wrap_content" 11 | android:onClick="save" 12 | android:text="save" /> 13 | 14 | <Button 15 | android:layout_width="match_parent" 16 | android:layout_height="wrap_content" 17 | android:onClick="read" 18 | android:text="read" /> 19 | 20 | <Button 21 | android:layout_width="match_parent" 22 | android:layout_height="wrap_content" 23 | android:onClick="clear" 24 | android:text="clear this JsonArray" /> 25 | 26 | <TextView 27 | android:id="@+id/tv_jsonarray_original" 28 | android:layout_width="wrap_content" 29 | android:layout_height="wrap_content" 30 | android:layout_margin="5dp" /> 31 | 32 | <TextView 33 | android:layout_width="match_parent" 34 | android:layout_height="1dp" 35 | android:background="#E5E5E5" /> 36 | 37 | <TextView 38 | android:id="@+id/tv_jsonarray_res" 39 | android:layout_width="wrap_content" 40 | android:layout_height="wrap_content" 41 | android:layout_margin="5dp" /> 42 | 43 | </LinearLayout> -------------------------------------------------------------------------------- /AsimpleCacheDemo/res/layout/activity_save_jsonobject.xml: -------------------------------------------------------------------------------- 1 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 | xmlns:tools="http://schemas.android.com/tools" 3 | android:layout_width="match_parent" 4 | android:layout_height="match_parent" 5 | android:gravity="center|top" 6 | android:orientation="vertical" > 7 | 8 | <Button 9 | android:layout_width="match_parent" 10 | android:layout_height="wrap_content" 11 | android:onClick="save" 12 | android:text="save" /> 13 | 14 | <Button 15 | android:layout_width="match_parent" 16 | android:layout_height="wrap_content" 17 | android:onClick="read" 18 | android:text="read" /> 19 | 20 | <Button 21 | android:layout_width="match_parent" 22 | android:layout_height="wrap_content" 23 | android:onClick="clear" 24 | android:text="clear this JsonObject" /> 25 | 26 | <TextView 27 | android:id="@+id/tv_jsonobject_original" 28 | android:layout_width="wrap_content" 29 | android:layout_height="wrap_content" 30 | android:layout_margin="5dp" /> 31 | 32 | <TextView 33 | android:layout_width="match_parent" 34 | android:layout_height="1dp" 35 | android:background="#E5E5E5" /> 36 | 37 | <TextView 38 | android:id="@+id/tv_jsonobject_res" 39 | android:layout_width="wrap_content" 40 | android:layout_height="wrap_content" 41 | android:layout_margin="5dp" /> 42 | 43 | </LinearLayout> -------------------------------------------------------------------------------- /AsimpleCacheDemo/res/layout/activity_save_object.xml: -------------------------------------------------------------------------------- 1 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 | xmlns:tools="http://schemas.android.com/tools" 3 | android:layout_width="match_parent" 4 | android:layout_height="match_parent" 5 | android:gravity="center|top" 6 | android:orientation="vertical" > 7 | 8 | <Button 9 | android:layout_width="match_parent" 10 | android:layout_height="wrap_content" 11 | android:onClick="save" 12 | android:text="save" /> 13 | 14 | <Button 15 | android:layout_width="match_parent" 16 | android:layout_height="wrap_content" 17 | android:onClick="read" 18 | android:text="read" /> 19 | 20 | <Button 21 | android:layout_width="match_parent" 22 | android:layout_height="wrap_content" 23 | android:onClick="clear" 24 | android:text="clear this Object" /> 25 | 26 | <TextView 27 | android:id="@+id/tv_object_original" 28 | android:layout_width="wrap_content" 29 | android:layout_height="wrap_content" 30 | android:layout_margin="5dp" /> 31 | 32 | <TextView 33 | android:layout_width="match_parent" 34 | android:layout_height="1dp" 35 | android:background="#E5E5E5" /> 36 | 37 | <TextView 38 | android:id="@+id/tv_object_res" 39 | android:layout_width="wrap_content" 40 | android:layout_height="wrap_content" 41 | android:layout_margin="5dp" /> 42 | 43 | </LinearLayout> -------------------------------------------------------------------------------- /AsimpleCacheDemo/res/layout/activity_save_string.xml: -------------------------------------------------------------------------------- 1 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 | xmlns:tools="http://schemas.android.com/tools" 3 | android:layout_width="match_parent" 4 | android:layout_height="match_parent" 5 | android:orientation="vertical" 6 | tools:context=".MainActivity" > 7 | 8 | <EditText 9 | android:id="@+id/et_string_input" 10 | android:layout_width="match_parent" 11 | android:layout_height="wrap_content" 12 | android:ems="10" 13 | android:hint="input something ..." > 14 | 15 | <requestFocus /> 16 | </EditText> 17 | 18 | <Button 19 | android:layout_width="match_parent" 20 | android:layout_height="wrap_content" 21 | android:onClick="save" 22 | android:text="save" /> 23 | 24 | <Button 25 | android:layout_width="match_parent" 26 | android:layout_height="wrap_content" 27 | android:onClick="read" 28 | android:text="read" /> 29 | 30 | <Button 31 | android:layout_width="match_parent" 32 | android:layout_height="wrap_content" 33 | android:onClick="clear" 34 | android:text="clear this String" /> 35 | 36 | <TextView 37 | android:id="@+id/tv_string_res" 38 | android:layout_width="match_parent" 39 | android:layout_height="wrap_content" /> 40 | 41 | </LinearLayout> -------------------------------------------------------------------------------- /AsimpleCacheDemo/res/menu/activity_save_jsonarray.xml: -------------------------------------------------------------------------------- 1 | <menu xmlns:android="http://schemas.android.com/apk/res/android" > 2 | 3 | <item 4 | android:id="@+id/menu_settings" 5 | android:orderInCategory="100" 6 | android:showAsAction="never" 7 | android:title="@string/menu_settings"/> 8 | 9 | </menu> -------------------------------------------------------------------------------- /AsimpleCacheDemo/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <resources> 3 | 4 | <string name="app_name">AsimpleCacheDemo</string> 5 | <string name="hello_world">AsimpleCacheDemo </string> 6 | <string name="menu_settings">Settings</string> 7 | <string name="title_activity_save_drawable">SaveDrawableActivity</string> 8 | <string name="title_activity_save_json_array">SaveJsonArrayActivity</string> 9 | 10 | </resources> -------------------------------------------------------------------------------- /AsimpleCacheDemo/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | <resources> 2 | 3 | <!-- 4 | Base application theme, dependent on API level. This theme is replaced 5 | by AppBaseTheme from res/values-vXX/styles.xml on newer devices. 6 | --> 7 | <style name="AppBaseTheme" parent="android:Theme.Light"> 8 | <!-- 9 | Theme customizations available in newer API levels can go in 10 | res/values-vXX/styles.xml, while customizations related to 11 | backward-compatibility can go here. 12 | --> 13 | </style> 14 | 15 | <!-- Application theme. --> 16 | <style name="AppTheme" parent="AppBaseTheme"> 17 | <!-- All customizations that are NOT specific to a particular API-level can go here. --> 18 | </style> 19 | 20 | </resources> -------------------------------------------------------------------------------- /AsimpleCacheDemo/src/com/yangfuhai/asimplecachedemo/AboutActivity.java: -------------------------------------------------------------------------------- 1 | package com.yangfuhai.asimplecachedemo; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | 6 | public class AboutActivity extends Activity { 7 | 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | setContentView(R.layout.activity_about); 12 | 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /AsimpleCacheDemo/src/com/yangfuhai/asimplecachedemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.yangfuhai.asimplecachedemo; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | 8 | /** 9 | * 10 | * @ClassName: MainActivity 11 | * @Description: 主界面 12 | * @Author Yoson Hao 13 | * @WebSite www.haoyuexing.cn 14 | * @Email haoyuexing@gmail.com 15 | * @Date 2013-8-8 下午2:08:47 16 | * 17 | */ 18 | public class MainActivity extends Activity { 19 | 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | setContentView(R.layout.activity_main); 24 | } 25 | 26 | public void string(View v) { 27 | startActivity(new Intent().setClass(this, SaveStringActivity.class)); 28 | } 29 | 30 | public void jsonobject(View v) { 31 | startActivity(new Intent().setClass(this, SaveJsonObjectActivity.class)); 32 | } 33 | 34 | public void jsonarray(View v) { 35 | startActivity(new Intent().setClass(this, SaveJsonArrayActivity.class)); 36 | } 37 | 38 | public void bitmap(View v) { 39 | startActivity(new Intent().setClass(this, SaveBitmapActivity.class)); 40 | } 41 | 42 | public void media(View v) { 43 | startActivity(new Intent().setClass(this, SaveMediaActivity.class)); 44 | } 45 | 46 | public void drawable(View v) { 47 | startActivity(new Intent().setClass(this, SaveDrawableActivity.class)); 48 | } 49 | 50 | public void object(View v) { 51 | startActivity(new Intent().setClass(this, SaveObjectActivity.class)); 52 | } 53 | 54 | public void about(View v) { 55 | startActivity(new Intent().setClass(this, AboutActivity.class)); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /AsimpleCacheDemo/src/com/yangfuhai/asimplecachedemo/SaveBitmapActivity.java: -------------------------------------------------------------------------------- 1 | package com.yangfuhai.asimplecachedemo; 2 | 3 | import org.afinal.simplecache.ACache; 4 | 5 | import android.app.Activity; 6 | import android.content.res.Resources; 7 | import android.graphics.Bitmap; 8 | import android.graphics.BitmapFactory; 9 | import android.os.Bundle; 10 | import android.view.View; 11 | import android.widget.ImageView; 12 | import android.widget.Toast; 13 | 14 | /** 15 | * 16 | * @ClassName: SaveBitmapActivity 17 | * @Description: 缓存bitmap 18 | * @Author Yoson Hao 19 | * @WebSite www.haoyuexing.cn 20 | * @Email haoyuexing@gmail.com 21 | * @Date 2013-8-7 下午5:20:37 22 | * 23 | */ 24 | public class SaveBitmapActivity extends Activity { 25 | 26 | private ImageView mIv_bitmap_res; 27 | 28 | private ACache mCache; 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | setContentView(R.layout.activity_save_bitmap); 34 | // 初始化控件 35 | initView(); 36 | 37 | mCache = ACache.get(this); 38 | } 39 | 40 | /** 41 | * 初始化控件 42 | */ 43 | private void initView() { 44 | mIv_bitmap_res = (ImageView) findViewById(R.id.iv_bitmap_res); 45 | } 46 | 47 | /** 48 | * 点击save事件 49 | * 50 | * @param v 51 | */ 52 | public void save(View v) { 53 | Resources res = getResources(); 54 | Bitmap bitmap = BitmapFactory.decodeResource(res, R.drawable.img_test); 55 | mCache.put("testBitmap", bitmap); 56 | } 57 | 58 | /** 59 | * 点击read事件 60 | * 61 | * @param v 62 | */ 63 | public void read(View v) { 64 | Bitmap testBitmap = mCache.getAsBitmap("testBitmap"); 65 | if (testBitmap == null) { 66 | Toast.makeText(this, "Bitmap cache is null ...", Toast.LENGTH_SHORT) 67 | .show(); 68 | mIv_bitmap_res.setImageBitmap(null); 69 | return; 70 | } 71 | mIv_bitmap_res.setImageBitmap(testBitmap); 72 | } 73 | 74 | /** 75 | * 点击clear事件 76 | * 77 | * @param v 78 | */ 79 | public void clear(View v) { 80 | mCache.remove("testBitmap"); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /AsimpleCacheDemo/src/com/yangfuhai/asimplecachedemo/SaveDrawableActivity.java: -------------------------------------------------------------------------------- 1 | package com.yangfuhai.asimplecachedemo; 2 | 3 | import org.afinal.simplecache.ACache; 4 | 5 | import android.os.Bundle; 6 | import android.view.View; 7 | import android.widget.ImageView; 8 | import android.widget.Toast; 9 | import android.app.Activity; 10 | import android.content.res.Resources; 11 | import android.graphics.drawable.Drawable; 12 | 13 | /** 14 | * 15 | * @ClassName: SaveDrawableActivity 16 | * @Description: 缓存drawable 17 | * @Author Yoson Hao 18 | * @WebSite www.haoyuexing.cn 19 | * @Email haoyuexing@gmail.com 20 | * @Date 2013-8-8 上午10:40:47 21 | * 22 | */ 23 | public class SaveDrawableActivity extends Activity { 24 | 25 | private ImageView mIv_drawable_res; 26 | 27 | private ACache mCache; 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_save_drawable); 33 | // 初始化控件 34 | initView(); 35 | 36 | mCache = ACache.get(this); 37 | } 38 | 39 | /** 40 | * 初始化控件 41 | */ 42 | private void initView() { 43 | mIv_drawable_res = (ImageView) findViewById(R.id.iv_drawable_res); 44 | } 45 | 46 | /** 47 | * 点击save事件 48 | * 49 | * @param v 50 | */ 51 | public void save(View v) { 52 | Resources res = getResources(); 53 | Drawable drawable = res.getDrawable(R.drawable.img_test); 54 | mCache.put("testDrawable", drawable); 55 | } 56 | 57 | /** 58 | * 点击read事件 59 | * 60 | * @param v 61 | */ 62 | public void read(View v) { 63 | Drawable testDrawable = mCache.getAsDrawable("testDrawable"); 64 | if (testDrawable == null) { 65 | Toast.makeText(this, "Drawable cache is null ...", 66 | Toast.LENGTH_SHORT).show(); 67 | mIv_drawable_res.setImageDrawable(null); 68 | return; 69 | } 70 | mIv_drawable_res.setImageDrawable(testDrawable); 71 | } 72 | 73 | /** 74 | * 点击clear事件 75 | * 76 | * @param v 77 | */ 78 | public void clear(View v) { 79 | mCache.remove("testDrawable"); 80 | } 81 | } -------------------------------------------------------------------------------- /AsimpleCacheDemo/src/com/yangfuhai/asimplecachedemo/SaveJsonArrayActivity.java: -------------------------------------------------------------------------------- 1 | package com.yangfuhai.asimplecachedemo; 2 | 3 | import org.afinal.simplecache.ACache; 4 | import org.json.JSONArray; 5 | import org.json.JSONException; 6 | import org.json.JSONObject; 7 | 8 | import android.os.Bundle; 9 | import android.view.View; 10 | import android.widget.TextView; 11 | import android.widget.Toast; 12 | import android.app.Activity; 13 | 14 | /** 15 | * 16 | * @ClassName: SaveJsonArrayActivity 17 | * @Description: 缓存jsonarray 18 | * @Author Yoson Hao 19 | * @WebSite www.haoyuexing.cn 20 | * @Email haoyuexing@gmail.com 21 | * @Date 2013-8-8 下午1:54:19 22 | * 23 | */ 24 | public class SaveJsonArrayActivity extends Activity { 25 | 26 | private TextView mTv_jsonarray_original, mTv_jsonarray_res; 27 | private JSONArray jsonArray; 28 | 29 | private ACache mCache; 30 | 31 | @Override 32 | protected void onCreate(Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | setContentView(R.layout.activity_save_jsonarray); 35 | // 初始化控件 36 | initView(); 37 | 38 | mCache = ACache.get(this); 39 | jsonArray = new JSONArray(); 40 | JSONObject yosonJsonObject = new JSONObject(); 41 | 42 | try { 43 | yosonJsonObject.put("name", "Yoson"); 44 | yosonJsonObject.put("age", 18); 45 | } catch (JSONException e) { 46 | e.printStackTrace(); 47 | } 48 | 49 | JSONObject michaelJsonObject = new JSONObject(); 50 | try { 51 | michaelJsonObject.put("name", "Michael"); 52 | michaelJsonObject.put("age", 25); 53 | } catch (JSONException e) { 54 | e.printStackTrace(); 55 | } 56 | 57 | jsonArray.put(yosonJsonObject); 58 | jsonArray.put(michaelJsonObject); 59 | 60 | mTv_jsonarray_original.setText(jsonArray.toString()); 61 | } 62 | 63 | /** 64 | * 初始化控件 65 | */ 66 | private void initView() { 67 | mTv_jsonarray_original = (TextView) findViewById(R.id.tv_jsonarray_original); 68 | mTv_jsonarray_res = (TextView) findViewById(R.id.tv_jsonarray_res); 69 | } 70 | 71 | /** 72 | * 点击save事件 73 | * 74 | * @param v 75 | */ 76 | public void save(View v) { 77 | mCache.put("testJsonArray", jsonArray); 78 | } 79 | 80 | /** 81 | * 点击read事件 82 | * 83 | * @param v 84 | */ 85 | public void read(View v) { 86 | JSONArray testJsonArray = mCache.getAsJSONArray("testJsonArray"); 87 | if (testJsonArray == null) { 88 | Toast.makeText(this, "JSONArray cache is null ...", 89 | Toast.LENGTH_SHORT).show(); 90 | mTv_jsonarray_res.setText(null); 91 | return; 92 | } 93 | mTv_jsonarray_res.setText(testJsonArray.toString()); 94 | } 95 | 96 | /** 97 | * 点击clear事件 98 | * 99 | * @param v 100 | */ 101 | public void clear(View v) { 102 | mCache.remove("testJsonArray"); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /AsimpleCacheDemo/src/com/yangfuhai/asimplecachedemo/SaveJsonObjectActivity.java: -------------------------------------------------------------------------------- 1 | package com.yangfuhai.asimplecachedemo; 2 | 3 | import org.afinal.simplecache.ACache; 4 | import org.json.JSONException; 5 | import org.json.JSONObject; 6 | 7 | import android.app.Activity; 8 | import android.os.Bundle; 9 | import android.view.View; 10 | import android.widget.TextView; 11 | import android.widget.Toast; 12 | 13 | /** 14 | * 15 | * @ClassName: SaveJsonObjectActivity 16 | * @Description: 缓存jsonobject 17 | * @Author Yoson Hao 18 | * @WebSite www.haoyuexing.cn 19 | * @Email haoyuexing@gmail.com 20 | * @Date 2013-8-8 上午11:42:30 21 | * 22 | */ 23 | public class SaveJsonObjectActivity extends Activity { 24 | 25 | private TextView mTv_jsonobject_original, mTv_jsonobject_res; 26 | private JSONObject jsonObject; 27 | 28 | private ACache mCache; 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | setContentView(R.layout.activity_save_jsonobject); 34 | // 初始化控件 35 | initView(); 36 | 37 | mCache = ACache.get(this); 38 | jsonObject = new JSONObject(); 39 | try { 40 | jsonObject.put("name", "Yoson"); 41 | jsonObject.put("age", 18); 42 | } catch (JSONException e) { 43 | e.printStackTrace(); 44 | } 45 | mTv_jsonobject_original.setText(jsonObject.toString()); 46 | } 47 | 48 | /** 49 | * 初始化控件 50 | */ 51 | private void initView() { 52 | mTv_jsonobject_original = (TextView) findViewById(R.id.tv_jsonobject_original); 53 | mTv_jsonobject_res = (TextView) findViewById(R.id.tv_jsonobject_res); 54 | } 55 | 56 | /** 57 | * 点击save事件 58 | * 59 | * @param v 60 | */ 61 | public void save(View v) { 62 | mCache.put("testJsonObject", jsonObject); 63 | } 64 | 65 | /** 66 | * 点击read事件 67 | * 68 | * @param v 69 | */ 70 | public void read(View v) { 71 | JSONObject testJsonObject = mCache.getAsJSONObject("testJsonObject"); 72 | if (testJsonObject == null) { 73 | Toast.makeText(this, "JSONObject cache is null ...", 74 | Toast.LENGTH_SHORT).show(); 75 | mTv_jsonobject_res.setText(null); 76 | return; 77 | } 78 | mTv_jsonobject_res.setText(testJsonObject.toString()); 79 | } 80 | 81 | /** 82 | * 点击clear事件 83 | * 84 | * @param v 85 | */ 86 | public void clear(View v) { 87 | mCache.remove("testJsonObject"); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /AsimpleCacheDemo/src/com/yangfuhai/asimplecachedemo/SaveMediaActivity.java: -------------------------------------------------------------------------------- 1 | package com.yangfuhai.asimplecachedemo; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.widget.TextView; 7 | import android.widget.Toast; 8 | 9 | import org.afinal.simplecache.ACache; 10 | 11 | import java.io.FileNotFoundException; 12 | import java.io.IOException; 13 | import java.io.InputStream; 14 | import java.io.OutputStream; 15 | import java.net.HttpURLConnection; 16 | import java.net.URL; 17 | 18 | /** 19 | * 20 | * @ClassName: SaveMediaActivity 21 | * @Description: 缓存bitmap 22 | * @Author Yoson Hao 23 | * @WebSite www.haoyuexing.cn 24 | * @Email haoyuexing@gmail.com 25 | * @Date 2013-8-7 下午5:20:37 26 | * 27 | */ 28 | public class SaveMediaActivity extends Activity implements Runnable { 29 | private String mUrl = "http://www.largesound.com/ashborytour/sound/brobob.mp3"; 30 | private static String CACHE_KEY = "brobob"; 31 | 32 | private TextView text; 33 | private ACache mCache; 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.activity_save_file); 39 | 40 | initView(); 41 | 42 | mCache = ACache.get(this); 43 | } 44 | 45 | /** 46 | * 初始化控件 47 | */ 48 | private void initView() { 49 | text = (TextView) findViewById(R.id.text); 50 | } 51 | 52 | /** 53 | * 点击save事件 54 | * 55 | * @param v 56 | */ 57 | public void save(View v) { 58 | text.setText("Loading..."); 59 | new Thread(this).start(); 60 | } 61 | 62 | /** 63 | * 点击read事件 64 | * 65 | * @param v 66 | */ 67 | public void read(View v) { 68 | InputStream stream = null; 69 | try { 70 | stream = mCache.get(CACHE_KEY); 71 | } catch (FileNotFoundException e) { 72 | e.printStackTrace(); 73 | } 74 | if (stream == null) { 75 | Toast.makeText(this, "Bitmap cache is null ...", Toast.LENGTH_SHORT) 76 | .show(); 77 | text.setText("file not found"); 78 | return; 79 | } 80 | try { 81 | text.setText("file size: " + stream.available()); 82 | } catch (IOException e) { 83 | text.setText("error " + e.getMessage()); 84 | } 85 | } 86 | 87 | /** 88 | * 点击clear事件 89 | * 90 | * @param v 91 | */ 92 | public void clear(View v) { 93 | mCache.remove(CACHE_KEY); 94 | } 95 | 96 | @Override 97 | public void run() { 98 | OutputStream ostream = null; 99 | try { 100 | ostream = mCache.put(CACHE_KEY); 101 | } catch (FileNotFoundException e) { 102 | e.printStackTrace(); 103 | } 104 | if (ostream == null){ 105 | Toast.makeText(this, "Open stream error!", Toast.LENGTH_SHORT) 106 | .show(); 107 | return; 108 | } 109 | try { 110 | URL u = new URL(mUrl); 111 | HttpURLConnection conn = (HttpURLConnection) u.openConnection(); 112 | conn.connect(); 113 | InputStream stream = conn.getInputStream(); 114 | 115 | byte[] buff = new byte[1024]; 116 | int counter; 117 | 118 | while ((counter = stream.read(buff)) > 0){ 119 | ostream.write(buff, 0, counter); 120 | } 121 | } catch (IOException e) { 122 | e.printStackTrace(); 123 | } finally { 124 | try { 125 | // cache update 126 | ostream.close(); 127 | } catch (IOException e) { 128 | e.printStackTrace(); 129 | } 130 | runOnUiThread(new Runnable() { 131 | @Override 132 | public void run() { 133 | text = (TextView) findViewById(R.id.text); 134 | text.setText("done..."); 135 | } 136 | }); 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /AsimpleCacheDemo/src/com/yangfuhai/asimplecachedemo/SaveObjectActivity.java: -------------------------------------------------------------------------------- 1 | package com.yangfuhai.asimplecachedemo; 2 | 3 | import org.afinal.simplecache.ACache; 4 | 5 | import com.yangfuhai.asimplecachedemo.beans.UserBean; 6 | 7 | import android.app.Activity; 8 | import android.os.Bundle; 9 | import android.view.View; 10 | import android.widget.TextView; 11 | import android.widget.Toast; 12 | 13 | /** 14 | * 15 | * @ClassName: SaveObjectActivity 16 | * @Description: 缓存jsonobject 17 | * @Author Yoson Hao 18 | * @WebSite www.haoyuexing.cn 19 | * @Email haoyuexing@gmail.com 20 | * @Date 2013-8-8 下午2:13:16 21 | * 22 | */ 23 | public class SaveObjectActivity extends Activity { 24 | 25 | private TextView mTv_object_original, mTv_object_res; 26 | private UserBean userBean; 27 | 28 | private ACache mCache; 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | setContentView(R.layout.activity_save_object); 34 | // 初始化控件 35 | initView(); 36 | 37 | mCache = ACache.get(this); 38 | userBean = new UserBean(); 39 | userBean.setAge("18"); 40 | userBean.setName("HaoYoucai"); 41 | mTv_object_original.setText(userBean.toString()); 42 | } 43 | 44 | /** 45 | * 初始化控件 46 | */ 47 | private void initView() { 48 | mTv_object_original = (TextView) findViewById(R.id.tv_object_original); 49 | mTv_object_res = (TextView) findViewById(R.id.tv_object_res); 50 | } 51 | 52 | /** 53 | * 点击save事件 54 | * 55 | * @param v 56 | */ 57 | public void save(View v) { 58 | mCache.put("testObject", userBean); 59 | } 60 | 61 | /** 62 | * 点击read事件 63 | * 64 | * @param v 65 | */ 66 | public void read(View v) { 67 | UserBean testObject = (UserBean) mCache.getAsObject("testObject"); 68 | if (testObject == null) { 69 | Toast.makeText(this, "Object cache is null ...", Toast.LENGTH_SHORT) 70 | .show(); 71 | mTv_object_res.setText(null); 72 | return; 73 | } 74 | mTv_object_res.setText(testObject.toString()); 75 | } 76 | 77 | /** 78 | * 点击clear事件 79 | * 80 | * @param v 81 | */ 82 | public void clear(View v) { 83 | mCache.remove("testObject"); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /AsimpleCacheDemo/src/com/yangfuhai/asimplecachedemo/SaveStringActivity.java: -------------------------------------------------------------------------------- 1 | package com.yangfuhai.asimplecachedemo; 2 | 3 | import org.afinal.simplecache.ACache; 4 | 5 | import android.app.Activity; 6 | import android.os.Bundle; 7 | import android.view.View; 8 | import android.widget.EditText; 9 | import android.widget.TextView; 10 | import android.widget.Toast; 11 | 12 | /** 13 | * 14 | * @ClassName: SaveStringActivity 15 | * @Description: 缓存string 16 | * @Author Yoson Hao 17 | * @WebSite www.haoyuexing.cn 18 | * @Email haoyuexing@gmail.com 19 | * @Date 2013-8-7 下午9:59:43 20 | * 21 | */ 22 | public class SaveStringActivity extends Activity { 23 | 24 | private EditText mEt_string_input; 25 | private TextView mTv_string_res; 26 | 27 | private ACache mCache; 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_save_string); 33 | // 初始化控件 34 | initView(); 35 | 36 | mCache = ACache.get(this); 37 | } 38 | 39 | /** 40 | * 初始化控件 41 | */ 42 | private void initView() { 43 | mEt_string_input = (EditText) findViewById(R.id.et_string_input); 44 | mTv_string_res = (TextView) findViewById(R.id.tv_string_res); 45 | } 46 | 47 | /** 48 | * 点击save事件 49 | * 50 | * @param v 51 | */ 52 | public void save(View v) { 53 | if (mEt_string_input.getText().toString().trim().length() == 0) { 54 | Toast.makeText( 55 | this, 56 | "Cuz u input is a nullcharacter ... So , when u press \"read\" , if do not show any result , plz don't be surprise", 57 | Toast.LENGTH_SHORT).show(); 58 | } 59 | mCache.put("testString", mEt_string_input.getText().toString()); 60 | } 61 | 62 | /** 63 | * 点击read事件 64 | * 65 | * @param v 66 | */ 67 | public void read(View v) { 68 | String testString = mCache.getAsString("testString"); 69 | if (testString == null) { 70 | Toast.makeText(this, "String cache is null ...", Toast.LENGTH_SHORT) 71 | .show(); 72 | mTv_string_res.setText(null); 73 | return; 74 | } 75 | mTv_string_res.setText(testString); 76 | } 77 | 78 | /** 79 | * 点击clear事件 80 | * 81 | * @param v 82 | */ 83 | public void clear(View v) { 84 | mCache.remove("testString"); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /AsimpleCacheDemo/src/com/yangfuhai/asimplecachedemo/beans/UserBean.java: -------------------------------------------------------------------------------- 1 | package com.yangfuhai.asimplecachedemo.beans; 2 | 3 | import java.io.Serializable; 4 | 5 | public class UserBean implements Serializable { 6 | 7 | /** 8 | * 9 | */ 10 | private static final long serialVersionUID = 1L; 11 | 12 | private String name; 13 | private String age; 14 | 15 | public String getName() { 16 | return name; 17 | } 18 | 19 | public void setName(String name) { 20 | this.name = name; 21 | } 22 | 23 | public String getAge() { 24 | return age; 25 | } 26 | 27 | public void setAge(String age) { 28 | this.age = age; 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | return "UserBean [name=" + name + ", age=" + age + "]"; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, and 10 | distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by the copyright 13 | owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all other entities 16 | that control, are controlled by, or are under common control with that entity. 17 | For the purposes of this definition, "control" means (i) the power, direct or 18 | indirect, to cause the direction or management of such entity, whether by 19 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the 20 | outstanding shares, or (iii) beneficial ownership of such entity. 21 | 22 | "You" (or "Your") shall mean an individual or Legal Entity exercising 23 | permissions granted by this License. 24 | 25 | "Source" form shall mean the preferred form for making modifications, including 26 | but not limited to software source code, documentation source, and configuration 27 | files. 28 | 29 | "Object" form shall mean any form resulting from mechanical transformation or 30 | translation of a Source form, including but not limited to compiled object code, 31 | generated documentation, and conversions to other media types. 32 | 33 | "Work" shall mean the work of authorship, whether in Source or Object form, made 34 | available under the License, as indicated by a copyright notice that is included 35 | in or attached to the work (an example is provided in the Appendix below). 36 | 37 | "Derivative Works" shall mean any work, whether in Source or Object form, that 38 | is based on (or derived from) the Work and for which the editorial revisions, 39 | annotations, elaborations, or other modifications represent, as a whole, an 40 | original work of authorship. For the purposes of this License, Derivative Works 41 | shall not include works that remain separable from, or merely link (or bind by 42 | name) to the interfaces of, the Work and Derivative Works thereof. 43 | 44 | "Contribution" shall mean any work of authorship, including the original version 45 | of the Work and any modifications or additions to that Work or Derivative Works 46 | thereof, that is intentionally submitted to Licensor for inclusion in the Work 47 | by the copyright owner or by an individual or Legal Entity authorized to submit 48 | on behalf of the copyright owner. For the purposes of this definition, 49 | "submitted" means any form of electronic, verbal, or written communication sent 50 | to the Licensor or its representatives, including but not limited to 51 | communication on electronic mailing lists, source code control systems, and 52 | issue tracking systems that are managed by, or on behalf of, the Licensor for 53 | the purpose of discussing and improving the Work, but excluding communication 54 | that is conspicuously marked or otherwise designated in writing by the copyright 55 | owner as "Not a Contribution." 56 | 57 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf 58 | of whom a Contribution has been received by Licensor and subsequently 59 | incorporated within the Work. 60 | 61 | 2. Grant of Copyright License. 62 | 63 | Subject to the terms and conditions of this License, each Contributor hereby 64 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, 65 | irrevocable copyright license to reproduce, prepare Derivative Works of, 66 | publicly display, publicly perform, sublicense, and distribute the Work and such 67 | Derivative Works in Source or Object form. 68 | 69 | 3. Grant of Patent License. 70 | 71 | Subject to the terms and conditions of this License, each Contributor hereby 72 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, 73 | irrevocable (except as stated in this section) patent license to make, have 74 | made, use, offer to sell, sell, import, and otherwise transfer the Work, where 75 | such license applies only to those patent claims licensable by such Contributor 76 | that are necessarily infringed by their Contribution(s) alone or by combination 77 | of their Contribution(s) with the Work to which such Contribution(s) was 78 | submitted. If You institute patent litigation against any entity (including a 79 | cross-claim or counterclaim in a lawsuit) alleging that the Work or a 80 | Contribution incorporated within the Work constitutes direct or contributory 81 | patent infringement, then any patent licenses granted to You under this License 82 | for that Work shall terminate as of the date such litigation is filed. 83 | 84 | 4. Redistribution. 85 | 86 | You may reproduce and distribute copies of the Work or Derivative Works thereof 87 | in any medium, with or without modifications, and in Source or Object form, 88 | provided that You meet the following conditions: 89 | 90 | You must give any other recipients of the Work or Derivative Works a copy of 91 | this License; and 92 | You must cause any modified files to carry prominent notices stating that You 93 | changed the files; and 94 | You must retain, in the Source form of any Derivative Works that You distribute, 95 | all copyright, patent, trademark, and attribution notices from the Source form 96 | of the Work, excluding those notices that do not pertain to any part of the 97 | Derivative Works; and 98 | If the Work includes a "NOTICE" text file as part of its distribution, then any 99 | Derivative Works that You distribute must include a readable copy of the 100 | attribution notices contained within such NOTICE file, excluding those notices 101 | that do not pertain to any part of the Derivative Works, in at least one of the 102 | following places: within a NOTICE text file distributed as part of the 103 | Derivative Works; within the Source form or documentation, if provided along 104 | with the Derivative Works; or, within a display generated by the Derivative 105 | Works, if and wherever such third-party notices normally appear. The contents of 106 | the NOTICE file are for informational purposes only and do not modify the 107 | License. You may add Your own attribution notices within Derivative Works that 108 | You distribute, alongside or as an addendum to the NOTICE text from the Work, 109 | provided that such additional attribution notices cannot be construed as 110 | modifying the License. 111 | You may add Your own copyright statement to Your modifications and may provide 112 | additional or different license terms and conditions for use, reproduction, or 113 | distribution of Your modifications, or for any such Derivative Works as a whole, 114 | provided Your use, reproduction, and distribution of the Work otherwise complies 115 | with the conditions stated in this License. 116 | 117 | 5. Submission of Contributions. 118 | 119 | Unless You explicitly state otherwise, any Contribution intentionally submitted 120 | for inclusion in the Work by You to the Licensor shall be under the terms and 121 | conditions of this License, without any additional terms or conditions. 122 | Notwithstanding the above, nothing herein shall supersede or modify the terms of 123 | any separate license agreement you may have executed with Licensor regarding 124 | such Contributions. 125 | 126 | 6. Trademarks. 127 | 128 | This License does not grant permission to use the trade names, trademarks, 129 | service marks, or product names of the Licensor, except as required for 130 | reasonable and customary use in describing the origin of the Work and 131 | reproducing the content of the NOTICE file. 132 | 133 | 7. Disclaimer of Warranty. 134 | 135 | Unless required by applicable law or agreed to in writing, Licensor provides the 136 | Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, 137 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, 138 | including, without limitation, any warranties or conditions of TITLE, 139 | NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are 140 | solely responsible for determining the appropriateness of using or 141 | redistributing the Work and assume any risks associated with Your exercise of 142 | permissions under this License. 143 | 144 | 8. Limitation of Liability. 145 | 146 | In no event and under no legal theory, whether in tort (including negligence), 147 | contract, or otherwise, unless required by applicable law (such as deliberate 148 | and grossly negligent acts) or agreed to in writing, shall any Contributor be 149 | liable to You for damages, including any direct, indirect, special, incidental, 150 | or consequential damages of any character arising as a result of this License or 151 | out of the use or inability to use the Work (including but not limited to 152 | damages for loss of goodwill, work stoppage, computer failure or malfunction, or 153 | any and all other commercial damages or losses), even if such Contributor has 154 | been advised of the possibility of such damages. 155 | 156 | 9. Accepting Warranty or Additional Liability. 157 | 158 | While redistributing the Work or Derivative Works thereof, You may choose to 159 | offer, and charge a fee for, acceptance of support, warranty, indemnity, or 160 | other liability obligations and/or rights consistent with this License. However, 161 | in accepting such obligations, You may act only on Your own behalf and on Your 162 | sole responsibility, not on behalf of any other Contributor, and only if You 163 | agree to indemnify, defend, and hold each Contributor harmless for any liability 164 | incurred by, or claims asserted against, such Contributor by reason of your 165 | accepting any such warranty or additional liability. 166 | 167 | END OF TERMS AND CONDITIONS 168 | 169 | APPENDIX: How to apply the Apache License to your work 170 | 171 | To apply the Apache License to your work, attach the following boilerplate 172 | notice, with the fields enclosed by brackets "[]" replaced with your own 173 | identifying information. (Don't include the brackets!) The text should be 174 | enclosed in the appropriate comment syntax for the file format. We also 175 | recommend that a file or class name and description of purpose be included on 176 | the same "printed page" as the copyright notice for easier identification within 177 | third-party archives. 178 | 179 | Copyright [yyyy] [name of copyright owner] 180 | 181 | Licensed under the Apache License, Version 2.0 (the "License"); 182 | you may not use this file except in compliance with the License. 183 | You may obtain a copy of the License at 184 | 185 | http://www.apache.org/licenses/LICENSE-2.0 186 | 187 | Unless required by applicable law or agreed to in writing, software 188 | distributed under the License is distributed on an "AS IS" BASIS, 189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 190 | See the License for the specific language governing permissions and 191 | limitations under the License. 192 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ASimpleCache 2 | ============ 3 | 4 | 5 | ---- 6 | ASimpleCache 是一个为android制定的 轻量级的 开源缓存框架。轻量到只有一个java文件(由十几个类精简而来)。 7 | 8 | 9 | --- 10 | ## 1、它可以缓存什么东西? 11 | 普通的字符串、JsonObject、JsonArray、Bitmap、Drawable、序列化的java对象,和 byte数据。 12 | 13 | 14 | ## 2、它有什么特色? 15 | * 特色主要是: 16 | * 1:轻,轻到只有一个JAVA文件。 17 | * 2:可配置,可以配置缓存路径,缓存大小,缓存数量等。 18 | * 3:可以设置缓存超时时间,缓存超时自动失效,并被删除。 19 | * 4:支持多进程。 20 | 21 | ##3、它在android中可以用在哪些场景? 22 | * 1、替换SharePreference当做配置文件 23 | * 2、可以缓存网络请求数据,比如oschina的android客户端可以缓存http请求的新闻内容,缓存时间假设为1个小时,超时后自动失效,让客户端重新请求新的数据,减少客户端流量,同时减少服务器并发量。 24 | * 3、您来说... 25 | 26 | 27 | ##4、如何使用 ASimpleCache? 28 | 以下有个小的demo,希望您能喜欢: 29 | 30 | ```java 31 | ACache mCache = ACache.get(this); 32 | mCache.put("test_key1", "test value"); 33 | mCache.put("test_key2", "test value", 10);//保存10秒,如果超过10秒去获取这个key,将为null 34 | mCache.put("test_key3", "test value", 2 * ACache.TIME_DAY);//保存两天,如果超过两天去获取这个key,将为null 35 | ``` 36 | 获取数据 37 | ```java 38 | ACache mCache = ACache.get(this); 39 | String value = mCache.getAsString("test_key1"); 40 | ``` 41 | 42 | 更多示例请见Demo 43 | 44 | #关于作者michael 45 | * 屌丝程序员一枚,喜欢开源。 46 | * 个人博客:[http://www.yangfuhai.com](http://www.yangfuhai.com) 47 | * 交流QQ群 : 192341294(已满) 246710918(未满) 48 | 49 | 50 | -------------------------------------------------------------------------------- /source/src/org/afinal/simplecache/ACache.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012-2013, Michael Yang 杨福海 (www.yangfuhai.com). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.afinal.simplecache; 17 | 18 | import java.io.BufferedReader; 19 | import java.io.BufferedWriter; 20 | import java.io.ByteArrayInputStream; 21 | import java.io.ByteArrayOutputStream; 22 | import java.io.File; 23 | import java.io.FileOutputStream; 24 | import java.io.FileReader; 25 | import java.io.FileWriter; 26 | import java.io.IOException; 27 | import java.io.ObjectInputStream; 28 | import java.io.ObjectOutputStream; 29 | import java.io.RandomAccessFile; 30 | import java.io.Serializable; 31 | import java.util.Collections; 32 | import java.util.HashMap; 33 | import java.util.Map; 34 | import java.util.Map.Entry; 35 | import java.util.Set; 36 | import java.util.concurrent.atomic.AtomicInteger; 37 | import java.util.concurrent.atomic.AtomicLong; 38 | 39 | import org.json.JSONArray; 40 | import org.json.JSONObject; 41 | 42 | import android.content.Context; 43 | import android.graphics.Bitmap; 44 | import android.graphics.BitmapFactory; 45 | import android.graphics.Canvas; 46 | import android.graphics.PixelFormat; 47 | import android.graphics.drawable.BitmapDrawable; 48 | import android.graphics.drawable.Drawable; 49 | 50 | /** 51 | * @author Michael Yang(www.yangfuhai.com) update at 2013.08.07 52 | */ 53 | public class ACache { 54 | public static final int TIME_HOUR = 60 * 60; 55 | public static final int TIME_DAY = TIME_HOUR * 24; 56 | private static final int MAX_SIZE = 1000 * 1000 * 50; // 50 mb 57 | private static final int MAX_COUNT = Integer.MAX_VALUE; // 不限制存放数据的数量 58 | private static Map<String, ACache> mInstanceMap = new HashMap<String, ACache>(); 59 | private ACacheManager mCache; 60 | 61 | public static ACache get(Context ctx) { 62 | return get(ctx, "ACache"); 63 | } 64 | 65 | public static ACache get(Context ctx, String cacheName) { 66 | File f = new File(ctx.getCacheDir(), cacheName); 67 | return get(f, MAX_SIZE, MAX_COUNT); 68 | } 69 | 70 | public static ACache get(File cacheDir) { 71 | return get(cacheDir, MAX_SIZE, MAX_COUNT); 72 | } 73 | 74 | public static ACache get(Context ctx, long max_zise, int max_count) { 75 | File f = new File(ctx.getCacheDir(), "ACache"); 76 | return get(f, max_zise, max_count); 77 | } 78 | 79 | public static ACache get(File cacheDir, long max_zise, int max_count) { 80 | ACache manager = mInstanceMap.get(cacheDir.getAbsoluteFile() + myPid()); 81 | if (manager == null) { 82 | manager = new ACache(cacheDir, max_zise, max_count); 83 | mInstanceMap.put(cacheDir.getAbsolutePath() + myPid(), manager); 84 | } 85 | return manager; 86 | } 87 | 88 | private static String myPid() { 89 | return "_" + android.os.Process.myPid(); 90 | } 91 | 92 | private ACache(File cacheDir, long max_size, int max_count) { 93 | if (!cacheDir.exists() && !cacheDir.mkdirs()) { 94 | throw new RuntimeException("can't make dirs in " 95 | + cacheDir.getAbsolutePath()); 96 | } 97 | mCache = new ACacheManager(cacheDir, max_size, max_count); 98 | } 99 | 100 | // ======================================= 101 | // ============ String数据 读写 ============== 102 | // ======================================= 103 | /** 104 | * 保存 String数据 到 缓存中 105 | * 106 | * @param key 107 | * 保存的key 108 | * @param value 109 | * 保存的String数据 110 | */ 111 | public void put(String key, String value) { 112 | File file = mCache.newFile(key); 113 | BufferedWriter out = null; 114 | try { 115 | out = new BufferedWriter(new FileWriter(file), 1024); 116 | out.write(value); 117 | } catch (IOException e) { 118 | e.printStackTrace(); 119 | } finally { 120 | if (out != null) { 121 | try { 122 | out.flush(); 123 | out.close(); 124 | } catch (IOException e) { 125 | e.printStackTrace(); 126 | } 127 | } 128 | mCache.put(file); 129 | } 130 | } 131 | 132 | /** 133 | * 保存 String数据 到 缓存中 134 | * 135 | * @param key 136 | * 保存的key 137 | * @param value 138 | * 保存的String数据 139 | * @param saveTime 140 | * 保存的时间,单位:秒 141 | */ 142 | public void put(String key, String value, int saveTime) { 143 | put(key, Utils.newStringWithDateInfo(saveTime, value)); 144 | } 145 | 146 | /** 147 | * 读取 String数据 148 | * 149 | * @param key 150 | * @return String 数据 151 | */ 152 | public String getAsString(String key) { 153 | File file = mCache.get(key); 154 | if (!file.exists()) 155 | return null; 156 | boolean removeFile = false; 157 | BufferedReader in = null; 158 | try { 159 | in = new BufferedReader(new FileReader(file)); 160 | String readString = ""; 161 | String currentLine; 162 | while ((currentLine = in.readLine()) != null) { 163 | readString += currentLine; 164 | } 165 | if (!Utils.isDue(readString)) { 166 | return Utils.clearDateInfo(readString); 167 | } else { 168 | removeFile = true; 169 | return null; 170 | } 171 | } catch (IOException e) { 172 | e.printStackTrace(); 173 | return null; 174 | } finally { 175 | if (in != null) { 176 | try { 177 | in.close(); 178 | } catch (IOException e) { 179 | e.printStackTrace(); 180 | } 181 | } 182 | if (removeFile) 183 | remove(key); 184 | } 185 | } 186 | 187 | // ======================================= 188 | // ============= JSONObject 数据 读写 ============== 189 | // ======================================= 190 | /** 191 | * 保存 JSONObject数据 到 缓存中 192 | * 193 | * @param key 194 | * 保存的key 195 | * @param value 196 | * 保存的JSON数据 197 | */ 198 | public void put(String key, JSONObject value) { 199 | put(key, value.toString()); 200 | } 201 | 202 | /** 203 | * 保存 JSONObject数据 到 缓存中 204 | * 205 | * @param key 206 | * 保存的key 207 | * @param value 208 | * 保存的JSONObject数据 209 | * @param saveTime 210 | * 保存的时间,单位:秒 211 | */ 212 | public void put(String key, JSONObject value, int saveTime) { 213 | put(key, value.toString(), saveTime); 214 | } 215 | 216 | /** 217 | * 读取JSONObject数据 218 | * 219 | * @param key 220 | * @return JSONObject数据 221 | */ 222 | public JSONObject getAsJSONObject(String key) { 223 | String JSONString = getAsString(key); 224 | try { 225 | JSONObject obj = new JSONObject(JSONString); 226 | return obj; 227 | } catch (Exception e) { 228 | e.printStackTrace(); 229 | return null; 230 | } 231 | } 232 | 233 | // ======================================= 234 | // ============ JSONArray 数据 读写 ============= 235 | // ======================================= 236 | /** 237 | * 保存 JSONArray数据 到 缓存中 238 | * 239 | * @param key 240 | * 保存的key 241 | * @param value 242 | * 保存的JSONArray数据 243 | */ 244 | public void put(String key, JSONArray value) { 245 | put(key, value.toString()); 246 | } 247 | 248 | /** 249 | * 保存 JSONArray数据 到 缓存中 250 | * 251 | * @param key 252 | * 保存的key 253 | * @param value 254 | * 保存的JSONArray数据 255 | * @param saveTime 256 | * 保存的时间,单位:秒 257 | */ 258 | public void put(String key, JSONArray value, int saveTime) { 259 | put(key, value.toString(), saveTime); 260 | } 261 | 262 | /** 263 | * 读取JSONArray数据 264 | * 265 | * @param key 266 | * @return JSONArray数据 267 | */ 268 | public JSONArray getAsJSONArray(String key) { 269 | String JSONString = getAsString(key); 270 | try { 271 | JSONArray obj = new JSONArray(JSONString); 272 | return obj; 273 | } catch (Exception e) { 274 | e.printStackTrace(); 275 | return null; 276 | } 277 | } 278 | 279 | // ======================================= 280 | // ============== byte 数据 读写 ============= 281 | // ======================================= 282 | /** 283 | * 保存 byte数据 到 缓存中 284 | * 285 | * @param key 286 | * 保存的key 287 | * @param value 288 | * 保存的数据 289 | */ 290 | public void put(String key, byte[] value) { 291 | File file = mCache.newFile(key); 292 | FileOutputStream out = null; 293 | try { 294 | out = new FileOutputStream(file); 295 | out.write(value); 296 | } catch (Exception e) { 297 | e.printStackTrace(); 298 | } finally { 299 | if (out != null) { 300 | try { 301 | out.flush(); 302 | out.close(); 303 | } catch (IOException e) { 304 | e.printStackTrace(); 305 | } 306 | } 307 | mCache.put(file); 308 | } 309 | } 310 | 311 | /** 312 | * 保存 byte数据 到 缓存中 313 | * 314 | * @param key 315 | * 保存的key 316 | * @param value 317 | * 保存的数据 318 | * @param saveTime 319 | * 保存的时间,单位:秒 320 | */ 321 | public void put(String key, byte[] value, int saveTime) { 322 | put(key, Utils.newByteArrayWithDateInfo(saveTime, value)); 323 | } 324 | 325 | /** 326 | * 获取 byte 数据 327 | * 328 | * @param key 329 | * @return byte 数据 330 | */ 331 | public byte[] getAsBinary(String key) { 332 | RandomAccessFile RAFile = null; 333 | boolean removeFile = false; 334 | try { 335 | File file = mCache.get(key); 336 | if (!file.exists()) 337 | return null; 338 | RAFile = new RandomAccessFile(file, "r"); 339 | byte[] byteArray = new byte[(int) RAFile.length()]; 340 | RAFile.read(byteArray); 341 | if (!Utils.isDue(byteArray)) { 342 | return Utils.clearDateInfo(byteArray); 343 | } else { 344 | removeFile = true; 345 | return null; 346 | } 347 | } catch (Exception e) { 348 | e.printStackTrace(); 349 | return null; 350 | } finally { 351 | if (RAFile != null) { 352 | try { 353 | RAFile.close(); 354 | } catch (IOException e) { 355 | e.printStackTrace(); 356 | } 357 | } 358 | if (removeFile) 359 | remove(key); 360 | } 361 | } 362 | 363 | // ======================================= 364 | // ============= 序列化 数据 读写 =============== 365 | // ======================================= 366 | /** 367 | * 保存 Serializable数据 到 缓存中 368 | * 369 | * @param key 370 | * 保存的key 371 | * @param value 372 | * 保存的value 373 | */ 374 | public void put(String key, Serializable value) { 375 | put(key, value, -1); 376 | } 377 | 378 | /** 379 | * 保存 Serializable数据到 缓存中 380 | * 381 | * @param key 382 | * 保存的key 383 | * @param value 384 | * 保存的value 385 | * @param saveTime 386 | * 保存的时间,单位:秒 387 | */ 388 | public void put(String key, Serializable value, int saveTime) { 389 | ByteArrayOutputStream baos = null; 390 | ObjectOutputStream oos = null; 391 | try { 392 | baos = new ByteArrayOutputStream(); 393 | oos = new ObjectOutputStream(baos); 394 | oos.writeObject(value); 395 | byte[] data = baos.toByteArray(); 396 | if (saveTime != -1) { 397 | put(key, data, saveTime); 398 | } else { 399 | put(key, data); 400 | } 401 | } catch (Exception e) { 402 | e.printStackTrace(); 403 | } finally { 404 | try { 405 | oos.close(); 406 | } catch (IOException e) { 407 | } 408 | } 409 | } 410 | 411 | /** 412 | * 读取 Serializable数据 413 | * 414 | * @param key 415 | * @return Serializable 数据 416 | */ 417 | public Object getAsObject(String key) { 418 | byte[] data = getAsBinary(key); 419 | if (data != null) { 420 | ByteArrayInputStream bais = null; 421 | ObjectInputStream ois = null; 422 | try { 423 | bais = new ByteArrayInputStream(data); 424 | ois = new ObjectInputStream(bais); 425 | Object reObject = ois.readObject(); 426 | return reObject; 427 | } catch (Exception e) { 428 | e.printStackTrace(); 429 | return null; 430 | } finally { 431 | try { 432 | if (bais != null) 433 | bais.close(); 434 | } catch (IOException e) { 435 | e.printStackTrace(); 436 | } 437 | try { 438 | if (ois != null) 439 | ois.close(); 440 | } catch (IOException e) { 441 | e.printStackTrace(); 442 | } 443 | } 444 | } 445 | return null; 446 | 447 | } 448 | 449 | // ======================================= 450 | // ============== bitmap 数据 读写 ============= 451 | // ======================================= 452 | /** 453 | * 保存 bitmap 到 缓存中 454 | * 455 | * @param key 456 | * 保存的key 457 | * @param value 458 | * 保存的bitmap数据 459 | */ 460 | public void put(String key, Bitmap value) { 461 | put(key, Utils.Bitmap2Bytes(value)); 462 | } 463 | 464 | /** 465 | * 保存 bitmap 到 缓存中 466 | * 467 | * @param key 468 | * 保存的key 469 | * @param value 470 | * 保存的 bitmap 数据 471 | * @param saveTime 472 | * 保存的时间,单位:秒 473 | */ 474 | public void put(String key, Bitmap value, int saveTime) { 475 | put(key, Utils.Bitmap2Bytes(value), saveTime); 476 | } 477 | 478 | /** 479 | * 读取 bitmap 数据 480 | * 481 | * @param key 482 | * @return bitmap 数据 483 | */ 484 | public Bitmap getAsBitmap(String key) { 485 | if (getAsBinary(key) == null) { 486 | return null; 487 | } 488 | return Utils.Bytes2Bimap(getAsBinary(key)); 489 | } 490 | 491 | // ======================================= 492 | // ============= drawable 数据 读写 ============= 493 | // ======================================= 494 | /** 495 | * 保存 drawable 到 缓存中 496 | * 497 | * @param key 498 | * 保存的key 499 | * @param value 500 | * 保存的drawable数据 501 | */ 502 | public void put(String key, Drawable value) { 503 | put(key, Utils.drawable2Bitmap(value)); 504 | } 505 | 506 | /** 507 | * 保存 drawable 到 缓存中 508 | * 509 | * @param key 510 | * 保存的key 511 | * @param value 512 | * 保存的 drawable 数据 513 | * @param saveTime 514 | * 保存的时间,单位:秒 515 | */ 516 | public void put(String key, Drawable value, int saveTime) { 517 | put(key, Utils.drawable2Bitmap(value), saveTime); 518 | } 519 | 520 | /** 521 | * 读取 Drawable 数据 522 | * 523 | * @param key 524 | * @return Drawable 数据 525 | */ 526 | public Drawable getAsDrawable(String key) { 527 | if (getAsBinary(key) == null) { 528 | return null; 529 | } 530 | return Utils.bitmap2Drawable(Utils.Bytes2Bimap(getAsBinary(key))); 531 | } 532 | 533 | /** 534 | * 获取缓存文件 535 | * 536 | * @param key 537 | * @return value 缓存的文件 538 | */ 539 | public File file(String key) { 540 | File f = mCache.newFile(key); 541 | if (f.exists()) 542 | return f; 543 | return null; 544 | } 545 | 546 | /** 547 | * 移除某个key 548 | * 549 | * @param key 550 | * @return 是否移除成功 551 | */ 552 | public boolean remove(String key) { 553 | return mCache.remove(key); 554 | } 555 | 556 | /** 557 | * 清除所有数据 558 | */ 559 | public void clear() { 560 | mCache.clear(); 561 | } 562 | 563 | /** 564 | * @title 缓存管理器 565 | * @author 杨福海(michael) www.yangfuhai.com 566 | * @version 1.0 567 | */ 568 | public class ACacheManager { 569 | private final AtomicLong cacheSize; 570 | private final AtomicInteger cacheCount; 571 | private final long sizeLimit; 572 | private final int countLimit; 573 | private final Map<File, Long> lastUsageDates = Collections 574 | .synchronizedMap(new HashMap<File, Long>()); 575 | protected File cacheDir; 576 | 577 | private ACacheManager(File cacheDir, long sizeLimit, int countLimit) { 578 | this.cacheDir = cacheDir; 579 | this.sizeLimit = sizeLimit; 580 | this.countLimit = countLimit; 581 | cacheSize = new AtomicLong(); 582 | cacheCount = new AtomicInteger(); 583 | calculateCacheSizeAndCacheCount(); 584 | } 585 | 586 | /** 587 | * 计算 cacheSize和cacheCount 588 | */ 589 | private void calculateCacheSizeAndCacheCount() { 590 | new Thread(new Runnable() { 591 | @Override 592 | public void run() { 593 | int size = 0; 594 | int count = 0; 595 | File[] cachedFiles = cacheDir.listFiles(); 596 | if (cachedFiles != null) { 597 | for (File cachedFile : cachedFiles) { 598 | size += calculateSize(cachedFile); 599 | count += 1; 600 | lastUsageDates.put(cachedFile, 601 | cachedFile.lastModified()); 602 | } 603 | cacheSize.set(size); 604 | cacheCount.set(count); 605 | } 606 | } 607 | }).start(); 608 | } 609 | 610 | private void put(File file) { 611 | int curCacheCount = cacheCount.get(); 612 | while (curCacheCount + 1 > countLimit) { 613 | long freedSize = removeNext(); 614 | cacheSize.addAndGet(-freedSize); 615 | 616 | curCacheCount = cacheCount.addAndGet(-1); 617 | } 618 | cacheCount.addAndGet(1); 619 | 620 | long valueSize = calculateSize(file); 621 | long curCacheSize = cacheSize.get(); 622 | while (curCacheSize + valueSize > sizeLimit) { 623 | long freedSize = removeNext(); 624 | curCacheSize = cacheSize.addAndGet(-freedSize); 625 | } 626 | cacheSize.addAndGet(valueSize); 627 | 628 | Long currentTime = System.currentTimeMillis(); 629 | file.setLastModified(currentTime); 630 | lastUsageDates.put(file, currentTime); 631 | } 632 | 633 | private File get(String key) { 634 | File file = newFile(key); 635 | Long currentTime = System.currentTimeMillis(); 636 | file.setLastModified(currentTime); 637 | lastUsageDates.put(file, currentTime); 638 | 639 | return file; 640 | } 641 | 642 | private File newFile(String key) { 643 | return new File(cacheDir, key.hashCode() + ""); 644 | } 645 | 646 | private boolean remove(String key) { 647 | File image = get(key); 648 | return image.delete(); 649 | } 650 | 651 | private void clear() { 652 | lastUsageDates.clear(); 653 | cacheSize.set(0); 654 | File[] files = cacheDir.listFiles(); 655 | if (files != null) { 656 | for (File f : files) { 657 | f.delete(); 658 | } 659 | } 660 | } 661 | 662 | /** 663 | * 移除旧的文件 664 | * 665 | * @return 666 | */ 667 | private long removeNext() { 668 | if (lastUsageDates.isEmpty()) { 669 | return 0; 670 | } 671 | 672 | Long oldestUsage = null; 673 | File mostLongUsedFile = null; 674 | Set<Entry<File, Long>> entries = lastUsageDates.entrySet(); 675 | synchronized (lastUsageDates) { 676 | for (Entry<File, Long> entry : entries) { 677 | if (mostLongUsedFile == null) { 678 | mostLongUsedFile = entry.getKey(); 679 | oldestUsage = entry.getValue(); 680 | } else { 681 | Long lastValueUsage = entry.getValue(); 682 | if (lastValueUsage < oldestUsage) { 683 | oldestUsage = lastValueUsage; 684 | mostLongUsedFile = entry.getKey(); 685 | } 686 | } 687 | } 688 | } 689 | 690 | long fileSize = calculateSize(mostLongUsedFile); 691 | if (mostLongUsedFile.delete()) { 692 | lastUsageDates.remove(mostLongUsedFile); 693 | } 694 | return fileSize; 695 | } 696 | 697 | private long calculateSize(File file) { 698 | return file.length(); 699 | } 700 | } 701 | 702 | /** 703 | * @title 时间计算工具类 704 | * @author 杨福海(michael) www.yangfuhai.com 705 | * @version 1.0 706 | */ 707 | private static class Utils { 708 | 709 | /** 710 | * 判断缓存的String数据是否到期 711 | * 712 | * @param str 713 | * @return true:到期了 false:还没有到期 714 | */ 715 | private static boolean isDue(String str) { 716 | return isDue(str.getBytes()); 717 | } 718 | 719 | /** 720 | * 判断缓存的byte数据是否到期 721 | * 722 | * @param data 723 | * @return true:到期了 false:还没有到期 724 | */ 725 | private static boolean isDue(byte[] data) { 726 | String[] strs = getDateInfoFromDate(data); 727 | if (strs != null && strs.length == 2) { 728 | String saveTimeStr = strs[0]; 729 | while (saveTimeStr.startsWith("0")) { 730 | saveTimeStr = saveTimeStr 731 | .substring(1, saveTimeStr.length()); 732 | } 733 | long saveTime = Long.valueOf(saveTimeStr); 734 | long deleteAfter = Long.valueOf(strs[1]); 735 | if (System.currentTimeMillis() > saveTime + deleteAfter * 1000) { 736 | return true; 737 | } 738 | } 739 | return false; 740 | } 741 | 742 | private static String newStringWithDateInfo(int second, String strInfo) { 743 | return createDateInfo(second) + strInfo; 744 | } 745 | 746 | private static byte[] newByteArrayWithDateInfo(int second, byte[] data2) { 747 | byte[] data1 = createDateInfo(second).getBytes(); 748 | byte[] retdata = new byte[data1.length + data2.length]; 749 | System.arraycopy(data1, 0, retdata, 0, data1.length); 750 | System.arraycopy(data2, 0, retdata, data1.length, data2.length); 751 | return retdata; 752 | } 753 | 754 | private static String clearDateInfo(String strInfo) { 755 | if (strInfo != null && hasDateInfo(strInfo.getBytes())) { 756 | strInfo = strInfo.substring(strInfo.indexOf(mSeparator) + 1, 757 | strInfo.length()); 758 | } 759 | return strInfo; 760 | } 761 | 762 | private static byte[] clearDateInfo(byte[] data) { 763 | if (hasDateInfo(data)) { 764 | return copyOfRange(data, indexOf(data, mSeparator) + 1, 765 | data.length); 766 | } 767 | return data; 768 | } 769 | 770 | private static boolean hasDateInfo(byte[] data) { 771 | return data != null && data.length > 15 && data[13] == '-' 772 | && indexOf(data, mSeparator) > 14; 773 | } 774 | 775 | private static String[] getDateInfoFromDate(byte[] data) { 776 | if (hasDateInfo(data)) { 777 | String saveDate = new String(copyOfRange(data, 0, 13)); 778 | String deleteAfter = new String(copyOfRange(data, 14, 779 | indexOf(data, mSeparator))); 780 | return new String[] { saveDate, deleteAfter }; 781 | } 782 | return null; 783 | } 784 | 785 | private static int indexOf(byte[] data, char c) { 786 | for (int i = 0; i < data.length; i++) { 787 | if (data[i] == c) { 788 | return i; 789 | } 790 | } 791 | return -1; 792 | } 793 | 794 | private static byte[] copyOfRange(byte[] original, int from, int to) { 795 | int newLength = to - from; 796 | if (newLength < 0) 797 | throw new IllegalArgumentException(from + " > " + to); 798 | byte[] copy = new byte[newLength]; 799 | System.arraycopy(original, from, copy, 0, 800 | Math.min(original.length - from, newLength)); 801 | return copy; 802 | } 803 | 804 | private static final char mSeparator = ' '; 805 | 806 | private static String createDateInfo(int second) { 807 | String currentTime = System.currentTimeMillis() + ""; 808 | while (currentTime.length() < 13) { 809 | currentTime = "0" + currentTime; 810 | } 811 | return currentTime + "-" + second + mSeparator; 812 | } 813 | 814 | /* 815 | * Bitmap → byte[] 816 | */ 817 | private static byte[] Bitmap2Bytes(Bitmap bm) { 818 | if (bm == null) { 819 | return null; 820 | } 821 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 822 | bm.compress(Bitmap.CompressFormat.PNG, 100, baos); 823 | return baos.toByteArray(); 824 | } 825 | 826 | /* 827 | * byte[] → Bitmap 828 | */ 829 | private static Bitmap Bytes2Bimap(byte[] b) { 830 | if (b.length == 0) { 831 | return null; 832 | } 833 | return BitmapFactory.decodeByteArray(b, 0, b.length); 834 | } 835 | 836 | /* 837 | * Drawable → Bitmap 838 | */ 839 | private static Bitmap drawable2Bitmap(Drawable drawable) { 840 | if (drawable == null) { 841 | return null; 842 | } 843 | // 取 drawable 的长宽 844 | int w = drawable.getIntrinsicWidth(); 845 | int h = drawable.getIntrinsicHeight(); 846 | // 取 drawable 的颜色格式 847 | Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 848 | : Bitmap.Config.RGB_565; 849 | // 建立对应 bitmap 850 | Bitmap bitmap = Bitmap.createBitmap(w, h, config); 851 | // 建立对应 bitmap 的画布 852 | Canvas canvas = new Canvas(bitmap); 853 | drawable.setBounds(0, 0, w, h); 854 | // 把 drawable 内容画到画布中 855 | drawable.draw(canvas); 856 | return bitmap; 857 | } 858 | 859 | /* 860 | * Bitmap → Drawable 861 | */ 862 | @SuppressWarnings("deprecation") 863 | private static Drawable bitmap2Drawable(Bitmap bm) { 864 | if (bm == null) { 865 | return null; 866 | } 867 | return new BitmapDrawable(bm); 868 | } 869 | } 870 | 871 | } 872 | --------------------------------------------------------------------------------