珍惜作者劳动成果,如需转载,请注明出处。 
http://blog.csdn.net/zhengzechuan91/article/details/50292871

Universal-Image-Loader 是一个优秀的图片加载开源项目,Github地址在 (Github地址) ,很多童鞋都在自己的项目中用到了。优秀的项目从来都是把简单留给开发者,把复杂封装在框架内部。ImageLoader作为Github上Star数过万的项目,备受开发者青睐,所以我们有必要搞清楚它的内部实现。

在上一篇博客中我们分析了ImageLoader框架的整体实现原理,还没有看过的直接到 深入解析开源项目之ImageLoader(一)框架篇 。


ImageLoader之内存缓存篇

项目截图:

由上图我们可以看出:

MemoryCache

  1. package com.nostra13.universalimageloader.cache.memory;
  2. import android.graphics.Bitmap;
  3. import java.util.Collection;
  4. public interface MemoryCache {
  5. boolean put(String key, Bitmap value);
  6.  
  7. Bitmap get(String key);
  8.  
  9. Bitmap remove(String key);
  10.  
  11. Collection<String> keys();
  12.  
  13. void clear();
  14. }

BaseMemoryCache,LimitedAgeMemoryCache,LruMemoryCache,FuzzyKeyMemoryCache

  1. public abstract class BaseMemoryCache implements MemoryCache {
  2.  
  3. private final Map<String, Reference<Bitmap>> softMap = Collections.synchronizedMap(new HashMap<String, Reference<Bitmap>>());
  4.  
  5. @Override
  6. public Bitmap get(String key) {
  7. Bitmap result = null;
  8. Reference<Bitmap> reference = softMap.get(key);
  9. if (reference != null) {
  10. result = reference.get();
  11. }
  12. return result;
  13. }
  14.  
  15. @Override
  16. public boolean put(String key, Bitmap value) {
  17. softMap.put(key, createReference(value));
  18. return true;
  19. }
  20.  
  21. @Override
  22. public Bitmap remove(String key) {
  23. Reference<Bitmap> bmpRef = softMap.remove(key);
  24. return bmpRef == null ? null : bmpRef.get();
  25. }
  26.  
  27. @Override
  28. public Collection<String> keys() {
  29. synchronized (softMap) {
  30. return new HashSet<String>(softMap.keySet());
  31. }
  32. }
  33.  
  34. @Override
  35. public void clear() {
  36. softMap.clear();
  37. }
  38.  
  39. protected abstract Reference<Bitmap> createReference(Bitmap value);
  40. }
  1. public class LimitedAgeMemoryCache implements MemoryCache {//也是对MemoryCache的装饰
  2.  
  3. private final MemoryCache cache;
  4.  
  5. private final long maxAge;
  6. private final Map<String, Long> loadingDates = Collections.synchronizedMap(new HashMap<String, Long>());
  7.  
  8. public LimitedAgeMemoryCache(MemoryCache cache, long maxAge) {
  9. this.cache = cache;
  10. this.maxAge = maxAge * 1000; // to milliseconds
  11. }
  12.  
  13. @Override
  14. public boolean put(String key, Bitmap value) {//时间超过我们设定的值,将其删除
  15. boolean putSuccesfully = cache.put(key, value);
  16. if (putSuccesfully) {
  17. loadingDates.put(key, System.currentTimeMillis());
  18. }
  19. return putSuccesfully;
  20. }

  21.   //对MemeryCache的get(String key)做了加强处理:当我们在获取内存Cache中的Bitmap时,如果超过最大存活时间则不返回
  22. @Override
  23. public Bitmap get(String key) {
  24. Long loadingDate = loadingDates.get(key);
  25. if (loadingDate != null && System.currentTimeMillis() - loadingDate > maxAge) {
  26. cache.remove(key);
  27. loadingDates.remove(key);
  28. }
  29.  
  30. return cache.get(key);
  31. }
  32.  
  33. @Override
  34. public Bitmap remove(String key) {
  35. loadingDates.remove(key);
  36. return cache.remove(key);
  37. }
  38.  
  39. @Override
  40. public Collection<String> keys() {
  41. return cache.keys();
  42. }
  43.  
  44. @Override
  45. public void clear() {
  46. cache.clear();
  47. loadingDates.clear();
  48. }
  49. }
  1. //开源框架默认的内存缓存类,缓存的是bitmap的强引用,
  2. public class LruMemoryCache implements MemoryCache {
  3.  
  4. private final LinkedHashMap<String, Bitmap> map;
  5. //缓存设定的最大值,maxSize 默认的情况下是程序进程占用内存总数的八分之一,单位是Byte。
  6. private final int maxSize;
  7. //** 缓存中已经占有的大小
  8. private int size;
  9.  
  10. public LruMemoryCache(int maxSize) {
  11. if (maxSize <= 0) {
  12. throw new IllegalArgumentException("maxSize <= 0");
  13. }
  14. this.maxSize = maxSize;
         //true表示排序的顺序是从最远使用到最近使用,而返回false顺序则为插入时的顺序。
  15. this.map = new LinkedHashMap<String, Bitmap>(0, 0.75f, true);
  16. }
  17.  
  18. @Override
  19. public final Bitmap get(String key) {
  20. if (key == null) {
  21. throw new NullPointerException("key == null");
  22. }
  23.  
  24. synchronized (this) {
  25. return map.get(key);
  26. }
  27. }
  28.  
  29. /** Caches {@code Bitmap} for {@code key}. The Bitmap is moved to the head of the queue. */
  30. @Override
  31. public final boolean put(String key, Bitmap value) {
  32. if (key == null || value == null) {
  33. throw new NullPointerException("key == null || value == null");
  34. }
  35.  
  36. synchronized (this) {
  37. //调用sizeOf这个函数获得该bitmap对象的占用内存的大小,并且让缓存总数增加
  38. size += sizeOf(key, value);
  39. //这里就是把对象放入容器中的最核心的一句代码,put()方法如果容器中已经有了此元素,则返回该元素的value值,否则添加进去并返回空
  40. Bitmap previous = map.put(key, value);
  41. if (previous != null) {
  42. //如果容器中已经有了此元素,则需要把增加的数量减掉
  43. size -= sizeOf(key, previous);
  44. }
  45. }
  46. //此函数计算是否超出最大限量,是则删除队尾元素
  47. trimToSize(maxSize);
  48. return true;
  49. }
  50.  
  51. //删除最先加入的元素,移除最远使用的Bitmap
  52. private void trimToSize(int maxSize) {
  53. while (true) {
  54. String key;
  55. Bitmap value;
  56. synchronized (this) {
  57. if (size < 0 || (map.isEmpty() && size != 0)) {
  58. throw new IllegalStateException(getClass().getName() + ".sizeOf() is reporting inconsistent results!");
  59. }
  60.  
  61. if (size <= maxSize || map.isEmpty()) {
  62. break;
  63. }
  64. //获取最先加入的元素
  65. Map.Entry<String, Bitmap> toEvict = map.entrySet().iterator().next();
  66. if (toEvict == null) {
  67. break;
  68. }
  69. key = toEvict.getKey();
  70. value = toEvict.getValue();
  71. map.remove(key);
  72. size -= sizeOf(key, value);
  73. }
  74. }
  75. }
  76.  
  77. @Override
  78. public final Bitmap remove(String key) {
  79. if (key == null) {
  80. throw new NullPointerException("key == null");
  81. }
  82.     //map实例化时并不是线程安全的,所以在所有的操作中都有同步锁。
  83. synchronized (this) {
          //存在则返回该Bitmap,不存在返回null
  84. Bitmap previous = map.remove(key);
  85. if (previous != null) {
              ////如果移除的Bitmap存在
  86. size -= sizeOf(key, previous);
  87. }
  88. return previous;
  89. }
  90. }
  91.  
  92. @Override
  93. public Collection<String> keys() {
  94. synchronized (this) {
  95. return new HashSet<String>(map.keySet());
  96. }
  97. }
  98.  
  99. @Override
  100. public void clear() {
  101. trimToSize(-1); // -1 will evict 0-sized elements
  102. }
  103.  
  104. private int sizeOf(String key, Bitmap value) {
  105. return value.getRowBytes() * value.getHeight();
  106. }
  107.  
  108. @Override
  109. public synchronized final String toString() {
  110. return String.format("LruCache[maxSize=%d]", maxSize);
  111. }
  112. }
  1. public class FuzzyKeyMemoryCache implements MemoryCache {//对MemoryCache的装饰
  2.  
  3. private final MemoryCache cache;
  4. private final Comparator<String> keyComparator;
  5.  
  6. public FuzzyKeyMemoryCache(MemoryCache cache, Comparator<String> keyComparator) {
  7. this.cache = cache;
  8. this.keyComparator = keyComparator;
  9. }

  10. /*对MemoryCache的put(String key, Bitmap value)方法进行加强处理:先移除key相同的Bitmap,再添加新的key对应的Bitmap*/
  11. @Override
  12. public boolean put(String key, Bitmap value) {
  13. // Search equal key and remove this entry
  14. synchronized (cache) {
  15. String keyToRemove = null;
  16. for (String cacheKey : cache.keys()) {
  17. if (keyComparator.compare(key, cacheKey) == 0) {
  18. keyToRemove = cacheKey;
  19. break;
  20. }
  21. }
  22. if (keyToRemove != null) {
  23. cache.remove(keyToRemove);
  24. }
  25. }
  26. return cache.put(key, value);
  27. }
  28.  
  29. @Override
  30. public Bitmap get(String key) {
  31. return cache.get(key);
  32. }
  33.  
  34. @Override
  35. public Bitmap remove(String key) {
  36. return cache.remove(key);
  37. }
  38.  
  39. @Override
  40. public void clear() {
  41. cache.clear();
  42. }
  43.  
  44. @Override
  45. public Collection<String> keys() {
  46. return cache.keys();
  47. }
  48. }

LimitedMemoryCache,WeakMemoryCache

  1. //重写LimitedMemoryCache主要是来实现removeNext()方法,以指定超过内存最大限定后移除Bitmap的规则。
    public abstract class LimitedMemoryCache extends BaseMemoryCache {
  2.  
  3. private static final int MAX_NORMAL_CACHE_SIZE_IN_MB = 16;
  4. private static final int MAX_NORMAL_CACHE_SIZE = MAX_NORMAL_CACHE_SIZE_IN_MB * 1024 * 1024;
  5.  
  6. private final int sizeLimit;//第2层最大缓存大小16M:多个线程只会读不会写
  7.  
  8. private final AtomicInteger cacheSize;//当前缓存的大小,原子操作:多个线程会对这个变量进行写
  9.  
  10. //强引用有引用变量指向时永远不会被垃圾回收。即使内存不足的时候宁愿报OOM也不被垃圾回收器回收,我们new的对象都是强引用
  11. private final List<Bitmap> hardCache = Collections.synchronizedList(new LinkedList<Bitmap>());
  12.  
  13. /** @param sizeLimit Maximum size for cache (in bytes) */
  14. public LimitedMemoryCache(int sizeLimit) {
  15. this.sizeLimit = sizeLimit;
  16. cacheSize = new AtomicInteger();
  17. if (sizeLimit > MAX_NORMAL_CACHE_SIZE) {
  18. L.w("You set too large memory cache size (more than %1$d Mb)", MAX_NORMAL_CACHE_SIZE_IN_MB);
  19. }
  20. }
  21.  
  22. @Override
  23. public boolean put(String key, Bitmap value) {
  24. boolean putSuccessfully = false;
  25. // Try to add value to hard cache
  26. int valueSize = getSize(value);
  27. int sizeLimit = getSizeLimit();
  28. int curCacheSize = cacheSize.get();
  29. if (valueSize < sizeLimit) {//如果一个图片大于第2层最大值,则不用进行移除加入第2层了
  30.  
  31. while (curCacheSize + valueSize > sizeLimit) {//小于最大值加入第二层,
  32. Bitmap removedValue = removeNext();//超过第二层最大值时4种移除第2层3层策略,第一层不移除
  33. if (hardCache.remove(removedValue)) {
  34. curCacheSize = cacheSize.addAndGet(-getSize(removedValue));
  35. }
  36. }
  37. hardCache.add(value);
  38. cacheSize.addAndGet(valueSize);
  39.  
  40. putSuccessfully = true;
  41. }
  42. // Add value to soft cache
  43. super.put(key, value);//加入第一层
  44. return putSuccessfully;
  45. }
  46.  
  47. @Override
  48. public Bitmap remove(String key) {
  49. Bitmap value = super.get(key);//第1层
  50. if (value != null) {//第1层有
  51. if (hardCache.remove(value)) {//第2层删除
  52. cacheSize.addAndGet(-getSize(value));
  53. }
  54. }
  55. return super.remove(key);//第1层删除,返回第1层删除的
  56. }
  57.  
  58. @Override
  59. public void clear() {
  60. hardCache.clear();//第2层删除
  61. cacheSize.set(0);
  62. super.clear();//第1层删除
  63. }
  64.  
  65. protected int getSizeLimit() {
  66. return sizeLimit;
  67. }
  68.  
  69. protected abstract int getSize(Bitmap value);
  70.  
  71. protected abstract Bitmap removeNext();
  72. }
  1. //这个类缓存bitmap的总大小没有限制,唯一不足的地方就是不稳定,缓存的图片容易被回收掉
  2. public class WeakMemoryCache extends BaseMemoryCache {
  3. @Override
  4. protected Reference<Bitmap> createReference(Bitmap value) {
  5. //弱引用通过weakReference类来实现,如果垃圾回收器扫描到有着WeakReference的对象,就会将其回收释放内存
  6. return new WeakReference<Bitmap>(value);
  7. }
  8. }

FIFOLimitedMemoryCache,LargestLimitedMemoryCache,LRULimitedMemoryCache,UsingFreqLimitedMemoryCache

  1. public class FIFOLimitedMemoryCache extends LimitedMemoryCache {
  2.  
  3. private final List<Bitmap> queue = Collections.synchronizedList(new LinkedList<Bitmap>());
  4.  
  5. public FIFOLimitedMemoryCache(int sizeLimit) {
  6. super(sizeLimit);//设置第2层最大值
  7. }
  8.  
  9. @Override
  10. public boolean put(String key, Bitmap value) {
  11. if (super.put(key, value)) {//第2层加了,1,3层也要加
  12. queue.add(value);
  13. return true;
  14. } else {//超过第2层总共最大值,第2,3层不添加,只加到第一层
  15. return false;
  16. }
  17. }
  18.  
  19. @Override
  20. public Bitmap remove(String key) {
  21. Bitmap value = super.get(key);//获取第1层软引用缓存有没有
  22. if (value != null) {//第1层有
  23. queue.remove(value);//第3层删除
  24. }
  25. return super.remove(key);//第2层
  26. }
  27.  
  28. @Override
  29. public void clear() {
  30. queue.clear();//第3层删除
  31. super.clear();//第2层
  32. }
  33.  
  34. @Override
  35. protected int getSize(Bitmap value) {
  36. return value.getRowBytes() * value.getHeight();
  37. }
  38.  
  39. @Override
  40. protected Bitmap removeNext() {
  41. return queue.remove(0);//删除第3层第1个
  42. }
  43.  
  44. @Override
  45. protected Reference<Bitmap> createReference(Bitmap value) {
  46. return new WeakReference<Bitmap>(value);
  47. }
  48. }
  1. public class LargestLimitedMemoryCache extends LimitedMemoryCache {
  2.  
  3. private final Map<Bitmap, Integer> valueSizes = Collections.synchronizedMap(new HashMap<Bitmap, Integer>());
  4.  
  5. public LargestLimitedMemoryCache(int sizeLimit) {
  6. super(sizeLimit);//设置第2层最大值
  7. }
  8.  
  9. @Override
  10. public boolean put(String key, Bitmap value) {
  11. if (super.put(key, value)) {//第2层加了,1,3层也要加。
  12. valueSizes.put(value, getSize(value));
  13. return true;
  14. } else {//第2层加不进去,3层不加,只加第一层
  15. return false;
  16. }
  17. }
  18.  
  19. @Override
  20. public Bitmap remove(String key) {
  21. Bitmap value = super.get(key);//第一层
  22. if (value != null) {//第一层有
  23. valueSizes.remove(value);//移除第三层
  24. }
  25. return super.remove(key);
  26. }
  27.  
  28. @Override
  29. public void clear() {
  30. valueSizes.clear();
  31. super.clear();
  32. }
  33.  
  34. @Override
  35. protected int getSize(Bitmap value) {
  36. return value.getRowBytes() * value.getHeight();
  37. }
  38.  
  39. @Override
  40. protected Bitmap removeNext() {//删除最大的bitmap对象
  41. Integer maxSize = null;
  42. Bitmap largestValue = null;
  43. Set<Entry<Bitmap, Integer>> entries = valueSizes.entrySet();
  44. synchronized (valueSizes) {
  45. for (Entry<Bitmap, Integer> entry : entries) {
  46. if (largestValue == null) {
  47. largestValue = entry.getKey();
  48. maxSize = entry.getValue();
  49. } else {
  50. Integer size = entry.getValue();
  51. if (size > maxSize) {
  52. maxSize = size;
  53. largestValue = entry.getKey();
  54. }
  55. }
  56. }
  57. }
  58. valueSizes.remove(largestValue);
  59. return largestValue;
  60. }
  61.  
  62. @Override
  63. protected Reference<Bitmap> createReference(Bitmap value) {
  64. return new WeakReference<Bitmap>(value);
  65. }
  66. }
  1. public class LRULimitedMemoryCache extends LimitedMemoryCache {
  2.  
  3. private static final int INITIAL_CAPACITY = 10;
  4. private static final float LOAD_FACTOR = 1.1f;
  5.  
  6. private final Map<String, Bitmap> lruCache = Collections.synchronizedMap(new LinkedHashMap<String, Bitmap>(INITIAL_CAPACITY, LOAD_FACTOR, true));
  7.  
  8. public LRULimitedMemoryCache(int maxSize) {
  9. super(maxSize);
  10. }
  11.  
  12. @Override
  13. public boolean put(String key, Bitmap value) {
  14. if (super.put(key, value)) {
  15. lruCache.put(key, value);
  16. return true;
  17. } else {
  18. return false;
  19. }
  20. }
  21.  
  22. @Override
  23. public Bitmap get(String key) {
  24. lruCache.get(key); // call "get" for LRU logic
  25. return super.get(key);
  26. }
  27.  
  28. @Override
  29. public Bitmap remove(String key) {
  30. lruCache.remove(key);
  31. return super.remove(key);
  32. }
  33.  
  34. @Override
  35. public void clear() {
  36. lruCache.clear();
  37. super.clear();
  38. }
  39.  
  40. @Override
  41. protected int getSize(Bitmap value) {
  42. return value.getRowBytes() * value.getHeight();
  43. }
  44.  
  45. @Override
  46. protected Bitmap removeNext() {
  47. Bitmap mostLongUsedValue = null;
  48. synchronized (lruCache) {
  49. Iterator<Entry<String, Bitmap>> it = lruCache.entrySet().iterator();
  50. if (it.hasNext()) {
  51. Entry<String, Bitmap> entry = it.next();
  52. mostLongUsedValue = entry.getValue();
  53. it.remove();
  54. }
  55. }
  56. return mostLongUsedValue;
  57. }
  58.  
  59. @Override
  60. protected Reference<Bitmap> createReference(Bitmap value) {
  61. return new WeakReference<Bitmap>(value);
  62. }
  63. }
  1. public class UsingFreqLimitedMemoryCache extends LimitedMemoryCache {
  2.  
  3. private final Map<Bitmap, Integer> usingCounts = Collections.synchronizedMap(new HashMap<Bitmap, Integer>());
  4.  
  5. public UsingFreqLimitedMemoryCache(int sizeLimit) {
  6. super(sizeLimit);
  7. }
  8.  
  9. @Override
  10. public boolean put(String key, Bitmap value) {
  11. if (super.put(key, value)) {
  12. usingCounts.put(value, 0);
  13. return true;
  14. } else {
  15. return false;
  16. }
  17. }
  18.  
  19. @Override
  20. public Bitmap get(String key) {//读取一次加1
  21. Bitmap value = super.get(key);
  22. // Increment usage count for value if value is contained in hardCahe
  23. if (value != null) {
  24. Integer usageCount = usingCounts.get(value);
  25. if (usageCount != null) {
  26. usingCounts.put(value, usageCount + 1);
  27. }
  28. }
  29. return value;
  30. }
  31.  
  32. @Override
  33. public Bitmap remove(String key) {
  34. Bitmap value = super.get(key);
  35. if (value != null) {
  36. usingCounts.remove(value);
  37. }
  38. return super.remove(key);
  39. }
  40.  
  41. @Override
  42. public void clear() {
  43. usingCounts.clear();
  44. super.clear();
  45. }
  46.  
  47. @Override
  48. protected int getSize(Bitmap value) {
  49. return value.getRowBytes() * value.getHeight();
  50. }
  51.  
  52. @Override
  53. protected Bitmap removeNext() {
  54. Integer minUsageCount = null;
  55. Bitmap leastUsedValue = null;
  56. Set<Entry<Bitmap, Integer>> entries = usingCounts.entrySet();
  57. synchronized (usingCounts) {
  58. for (Entry<Bitmap, Integer> entry : entries) {
  59. if (leastUsedValue == null) {
  60. leastUsedValue = entry.getKey();
  61. minUsageCount = entry.getValue();
  62. } else {
  63. Integer lastValueUsage = entry.getValue();
  64. if (lastValueUsage < minUsageCount) {
  65. minUsageCount = lastValueUsage;
  66. leastUsedValue = entry.getKey();
  67. }
  68. }
  69. }
  70. }
  71. usingCounts.remove(leastUsedValue);
  72. return leastUsedValue;
  73. }
  74.  
  75. @Override
  76. protected Reference<Bitmap> createReference(Bitmap value) {
  77. return new WeakReference<Bitmap>(value);
  78. }
  79. }

深入解析开源项目之Universal-Image-Loader(二)内存---缓存篇的更多相关文章

  1. 开源项目MultiChoiceAdapter详解(二)——MultiChoiceArrayAdapter的使用

    MultiChoiceArrayAdapter其实就是可以多选的ArrayAdapter了,ArrayAdpter我们已经很熟悉了.MultiChoiceArrayAdapter这个类是抽象类,所以使 ...

  2. 开源项目SMSS开发指南(二)——基于libevent的线程池

    libevent是一套轻量级的网络库,基于事件驱动开发.能够实现多线程的多路复用和注册事件响应.本文将介绍libevent的基本功能以及如何利用libevent开发一个线程池. 一. 使用指南 监听服 ...

  3. 开源项目PullToRefresh详解(二)——PullToRefreshGridView

    这里介绍的是PullToRefreshGridView的使用方法,和之前的PullToRefreshListView方法如出一辙,因为这个开源项目模块化很棒,所以很容易实现.等于说我们可以按照之前使用 ...

  4. 深入解析开源项目之Universal-Image-Loader(二)硬盘---缓存篇

    文件命名: FileNameGenerator,HashCodeFileNameGenerator,Md5FileNameGenerator package com.nostra13.universa ...

  5. Diycode开源项目 如何解决InputMethodManager造成的内存泄漏问题

    1.内存泄漏的状况及原因 1.1.利用LeakCanary查看内存泄漏的状况 1.2.内存泄漏怎么产生的呢? InputMethodManager.mServicedView持有一个最后聚焦View的 ...

  6. .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现

    本篇我将带着大家一起来对Dapper进行下封装并实现基本的增删改查.分页操作的同步异步方法的实现(已实现MSSQL,MySql,PgSQL).同时我们再实现一下仓储层的代码生成器,这样的话,我们只需要 ...

  7. apache基金会开源项目简介

    apache基金会开源项目简介   项目名称 描述 HTTP Server 互联网上首屈一指的HTTP服务器 Abdera Apache  Abdera项目的目标是建立一个功能完备,高效能的IETF ...

  8. 值得研究的J2EE开源项目推荐

    导读:笔者在学习J2EE的过程中发现了一些很有用,而且很值得学习的开源项目,在此推荐给大家. 关键词:J2EE 开源项目 J2SE JBoss SOA EJB   这篇文章写在我研究J2SE.J2EE ...

  9. 可删除超炫&amp;多种特效的Card视图(改造自cardsui-for-android开源项目),提供DEMO下载

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990).谢谢支持!        实例Demo下载地址在本文最后 简介 这个Demo主要是使用了cardsui ...

随机推荐

  1. ModelForm views.py

    from django.shortcuts import render from django import forms from django.forms import fields from ap ...

  2. Dictionaries

    A dictionary is like a list, but more general. In a list, the indices have to be integers; in a dict ...

  3. HDFS文件上传下载过程(详图)

  4. 使用物化视图解决GoldenGate不能使用中文表名问题

    源端: conn sh/sh create table "学生" ("学号" number primary key,"姓名" varchar ...

  5. UI Framework-1: Aura

    Aura (obsolete) This document is still good for a high level overview, with contact information, but ...

  6. 运营商 WLAN

    运营商 WLAN 运营商 WLAN 是 Android 9 中引入的一项功能,该功能可让设备自动连接到运营商实现的 WLAN 网络.在高度拥塞或信号覆盖范围较小的区域(如体育场或地铁站),运营商 WL ...

  7. iOS开发——打包报错error: linker command failed with exit code 1

    真机运行没问题,打包报错: clang: error: linker command failed with exit code 1 (use -v to see invocation) 原因:在Xc ...

  8. Test-我喜欢LInux

    测试发帖流程 哈哈 习惯一下先.

  9. WHU 1542 Countries (floyd)

    题意: 在小明出生的星球X上有n国家. 一些国家通过结盟而拥有良好的双边关系,因此他们的公民得益于这些政策,使得所有这些国家之间的旅行变得免费. 但是,不同联盟之间的旅行就不是这么容易了.如果可能,它 ...

  10. ArcGIS api for javascript——用第二个服务的范围设置地图范围

    描述 本例展示了如何设置地图的范围为地图其中一个图层的范围.本例有两个图层:ArcGIS Online上的世界地图图层ArcGISTiledMapServiceLayer和堪萨斯州的要素的图层ArcG ...