我们知道从Android2.*后google不推荐使用软饮用了, 因为google优化了gc回收机制, 每次gc时不管内存是否充足都会释放软引用。 google推荐使用LruCache.java替代软引用, 而LruCache内部维护个LinkedList, 实际上就是当内存不足时删掉最远使用的对象。
在分析fresco内存相关的源码时, 可以到有个类叫OOMSoftReferecne, 使用3个SoftReference指向同一个对象。 看最后一句翻译过来就是“只有在OOM时才会释放这个引用”TLDR: It's a reference that's cleared if and only
if we otherwise would have encountered an OOM. 翻译过来就是“只有在OOM时才会释放这个引用”, 多个软引用放到一起相当于强引用了
。
/** * To eliminate the possibility of some of our objects causing an OutOfMemoryError when they are * not used, we reference them via SoftReferences. * What is a SoftReference? * <a href="http://developer.android.com/reference/java/lang/ref/SoftReference.html"></a> * <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/ref/SoftReference.html"></a> * A Soft Reference is a reference that is cleared when its referent is not strongly reachable and * there is memory pressure. SoftReferences as implemented by Dalvik blindly treat every second * SoftReference as a WeakReference every time a garbage collection happens, - i.e. clear it unless * there is something else referring to it: * <a href="https://goo.gl/Pe6aS7">dalvik</a> * <a href="https://goo.gl/BYaUZE">art</a> * It will however clear every SoftReference if we don't have enough memory to satisfy an * allocation after a garbage collection. * * This means that as long as one of the soft references stays alive, they all stay alive. If we * have two SoftReferences next to each other on the heap, both pointing to the same object, then * we are guaranteed that neither will be cleared until we otherwise would have thrown an * OutOfMemoryError. Since we can't strictly guarantee the location of objects on the heap, we use * 3 just to be on the safe side. * TLDR: It's a reference that's cleared if and only if we otherwise would have encountered an OOM. */ public class OOMSoftReference<T> { SoftReference<T> softRef1; SoftReference<T> softRef2; SoftReference<T> softRef3; public OOMSoftReference() { softRef1 = null; softRef2 = null; softRef3 = null; } public void set(@Nonnull T hardReference) { softRef1 = new SoftReference<T>(hardReference); softRef2 = new SoftReference<T>(hardReference); softRef3 = new SoftReference<T>(hardReference); } @Nullable public T get() { return (softRef1 == null ? null : softRef1.get()); } public void clear() { if (softRef1 != null) { softRef1.clear(); softRef1 = null; } if (softRef2 != null) { softRef2.clear(); softRef2 = null; } if (softRef3 != null) { softRef3.clear(); softRef3 = null; } } }为了验证上述说法, 我写个简单的demo。
public class MainActivity extends AppCompatActivity { SoftReference<?> softReference1; SoftReference<?> softReference2; SoftReference<?> softReference3; TextView tvTest; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Bitmap bmp = Bitmap.createBitmap(2048, 2048, Bitmap.Config.ARGB_8888); Log.d("brycegao", "bitmap size:" + bmp.getByteCount()); softReference1 = new SoftReference<Bitmap>(bmp); //softReference2 = new SoftReference<Bitmap>(bmp); //softReference3 = new SoftReference<Bitmap>(bmp); tvTest = (TextView) findViewById(R.id.tv_test); tvTest.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { System.gc(); //强制内存回收 Object obj = softReference1.get(); Log.d("brycegao", "softreference:" + obj); } }); } }
09-03 09:21:15.371 6530-6530/com.example.brycegao.myapplication D/brycegao: bitmap size:16777216
09-03 09:21:15.502 6530-7062/com.example.brycegao.myapplication V/RenderScript: 0x9ffde000 Launching thread(s), CPUs 4
09-03 09:21:24.872 6530-6530/com.example.brycegao.myapplication D/brycegao: softreference:null
从日志可以看出只有一个软饮用指向bitmap时, gc时会回收这块内存的。
放开softReference2,softReference3的注释, 即使用3个软饮用再次测试:
09-03 09:37:19.621 23036-23036/com.example.brycegao.myapplication D/brycegao: bitmap size:16777216
09-03 09:37:30.462 23036-23036/com.example.brycegao.myapplication D/brycegao: softreference:android.graphics.Bitmap@3067335
果然!!! 软饮用指向的大图片没被回收, 以后在项目管理内存时可以使用这种做法, 即多个软饮用指向同一个对象

本文探讨了Android中软引用的特殊用法,通过创建多个软引用指向同一对象来确保仅在发生内存溢出时该对象才被垃圾回收机制清理。这种方法能够有效避免因单一软引用导致的对象过早回收。
6939

被折叠的 条评论
为什么被折叠?



