简单的说明
WeakReference:弱引用–>随时可能会被垃圾回收器回收,不一定要等到虚拟机内存不足时才强制回收。要获取对象时,同样可以调用get方法。所以WeakReference一般用来防止内存泄漏,要保证内存被虚拟机回收。
SoftReference:软引用–>当虚拟机内存不足时,将会回收它指向的对象;需要获取对象时,可以调用get方法。所以,SoftReference多用作来实现缓存机制(cache)
例子
我们以packages目录下的应用为例子,可以查看到此目录下WeakReference和SoftReference 使用情况:
—- WeakReference Matches (284 in 88 files) —-
WeakReference 在88个文件,使用了284次
—- SoftReference Matches (71 in 13 files) —-
SoftReference 在13个文件,使用了71次
从上面可以看出,WeakReference 的使用比SoftReference 更常用。
WeakReference
第一个例子:
ZenRuleSelectionDialog.java (apps\settings\src\com\android\settings\notification):
在AsyncTask中更新R.id.icon的ImageView的图片:
private class LoadIconTask extends AsyncTask<ApplicationInfo, Void, Drawable> {
private final WeakReference<ImageView> viewReference;
public LoadIconTask(ImageView view) {
viewReference = new WeakReference<>(view);
}
@Override
protected Drawable doInBackground(ApplicationInfo... params) {
return params[0].loadIcon(mPm);
}
@Override
protected void onPostExecute(Drawable icon) {
if (icon != null) {
final ImageView view = viewReference.get();
if (view != null) {
view.setImageDrawable(icon);
}
}
}
}
使用方法:
LoadIconTask task = new LoadIconTask((ImageView) v.findViewById(R.id.icon));
task.execute(info);
此方法是对R.id.icon的ImageView来使用WeakReference,以防止内存泄漏。
第二个例子:
AddAccessoryActivity.java (apps\tvsettings\settings\src\com\android\tv\settings\accessories):
定义static内部类MessageHandler :
private static class MessageHandler extends Handler {
private WeakReference<AddAccessoryActivity> mActivityRef = new WeakReference<>(null);
public void setActivity(AddAccessoryActivity activity) {
mActivityRef = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
final AddAccessoryActivity activity = mActivityRef.get();
if (activity == null) {
return;
}
switch (msg.what) {
case MSG_UPDATE_VIEW:
activity.updateView();
break;
case MSG_REMOVE_CANCELED:
activity.mCancelledAddress = ADDRESS_NONE;
activity.updateView();
break;
case MSG_PAIRING_COMPLETE:
activity.finish();
break;
case MSG_OP_TIMEOUT:
activity.handlePairingTimeout();
break;
case MSG_RESTART:
if (activity.mBluetoothPairer != null) {
activity.mBluetoothPairer.start();
activity.mBluetoothPairer.cancelPairing();
}
break;
...........
使用:
// Internal message handler
private final MessageHandler mMsgHandler = new MessageHandler();
..................
mMsgHandler.setActivity(this);
..................
mMsgHandler.removeCallbacksAndMessages(null);
..................
mMsgHandler.sendEmptyMessageDelayed(MSG_OP_TIMEOUT, timeout);
..................
此例子为常用的m内部Handler类的对activity的弱引用的例子。
第三个例子:
BluetoothBipCoverArt.java (apps\bluetooth\src\com\android\bluetooth\bip):
private static class RemoteControllerWeak implements RemoteController.OnClientUpdateListener {
//定义弱引用
private final WeakReference<Handler> mLocalHandler;
public RemoteControllerWeak(Handler handler) {
//弱引用赋值
mLocalHandler = new WeakReference<Handler>(handler);
}
..........................
@Override
public void onClientMetadataUpdate(MetadataEditor metadataEditor) {
Handler handler = mLocalHandler.get();
if (handler != null) {
handler.obtainMessage(MSG_SET_METADATA, 0, 0, metadataEditor).sendToTarget();
}
}
............................
使用方法:
mRemoteControllerCb = new RemoteControllerWeak(mBipCoverArtHandler);
此例子,主要是对mBipCoverArtHandler实现弱引用。
SoftReference
第一个例子:
KeyboardLayoutSet.java (inputmethods\latinime\java\src\com\android\inputmethod\keyboard)
定义一个static的缓存HashMap:
private static final HashMap<KeyboardId, SoftReference<Keyboard>> sKeyboardCache =
new HashMap<>();
实现此缓存的效果:
private Keyboard getKeyboard(final ElementParams elementParams, final KeyboardId id) {
//先判断是否存在缓存
final SoftReference<Keyboard> ref = sKeyboardCache.get(id);
final Keyboard cachedKeyboard = (ref == null) ? null : ref.get();
if (cachedKeyboard != null) {
if (DEBUG_CACHE) {
Log.d(TAG, "keyboard cache size=" + sKeyboardCache.size() + ": HIT id=" + id);
}
return cachedKeyboard;
}
.........
//给其赋值
sKeyboardCache.put(id, new SoftReference<>(keyboard));
.........
清除缓存:
private static void clearKeyboardCache() {
sKeyboardCache.clear();
...........
}
第二个例子:
Sources.java (experimental\loaderapp\src\com\android\loaderapp\model):
public class Sources extends BroadcastReceiver implements OnAccountsUpdateListener {
................
private static SoftReference<Sources> sInstance = null;
................
public static synchronized Sources getInstance(Context context) {
Sources sources = sInstance == null ? null : sInstance.get();
if (sources == null) {
sources = new Sources(context);
sInstance = new SoftReference<Sources>(sources);
}
return sources;
}
................
这个软引用实现缓存的实现非常明显
参考资料
1.Android中的软引用(SoftRefrerence)和弱引用(WeakReference)
http://blog.csdn.net/stevenhu_223/article/details/18360397
2.WeakReference在Android中的使用
http://blog.csdn.net/u012951554/article/details/48055939
3.Java弱引用(WeakReference)的理解与使用
http://blog.csdn.net/zmx729618/article/details/54093532