回答:
WeakReference
Androidでのaの使用は、普通のJavaでの使用と何の違いもありません。これは、詳細な説明を提供する優れたガイドです:弱い参照の理解。
オブジェクトへの参照が必要なときはいつでも使用することを検討する必要がありますが、その参照がオブジェクトをガベージコレクターから保護する必要はありません。古典的な例は、メモリ使用量が高くなりすぎた場合にガベージコレクションの対象とするキャッシュです(多くの場合で実装されますWeakHashMap
)。
チェックアウトしてくださいSoftReference
とPhantomReference
同様。
編集:トムは、でキャッシュを実装することについていくつかの懸念を提起しましたWeakHashMap
。ここに問題を説明する記事があります:WeakHashMapはキャッシュではありません!
トムは不満があったことは正しい、WeakHashMap
キャッシングによるNetbeansのパフォーマンスの低下について。
でキャッシュを実装しWeakHashMap
、それをで実装した独自の手動ロールキャッシュと比較することは、良い学習経験になると思いますSoftReference
。現実の世界では、Apache JCSのようなサードパーティのライブラリを使用する方が理にかなっているため、おそらくこれらのソリューションのどちらも使用しないでしょう。
WeakHashMap
キャッシュとして使用すると致命的です。エントリは、作成されるとすぐに削除できます。これは、テスト時にはおそらく発生しませんが、使用しているときには発生する可能性があります。注目すべきことに、これにより、NetBeansはCPUを効果的に100%停止させることができます。
WeakHashMap
場合、正しく選択されていてもキャッシュが実装されていることは正しい選択ではないことを
[編集2]別の良い例を見つけましたWeakReference
。「ビットマップを効率的に表示する」トレーニングガイドの「UIスレッド」ページからのビットマップの処理はWeakReference
、AsyncTaskでの1つの使用法を示しています。
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private int data = 0;
public BitmapWorkerTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
}
// Decode image in background.
@Override
protected Bitmap doInBackground(Integer... params) {
data = params[0];
return decodeSampledBitmapFromResource(getResources(), data, 100, 100));
}
// Once complete, see if ImageView is still around and set bitmap.
@Override
protected void onPostExecute(Bitmap bitmap) {
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}
それは言う、
ImageViewへのWeakReferenceにより、AsyncTaskがImageViewおよびそれが参照するものがガベージコレクションされるのを防ぐことができます。タスクが終了してもImageViewがまだ存在する保証はないため、onPostExecute()で参照も確認する必要があります。たとえば、ユーザーがアクティビティから移動した場合や、タスクが完了する前に構成変更が発生した場合、ImageViewは存在しなくなる可能性があります。
幸せなコーディング!
[編集]私WeakReference
はfacebook-android-sdkからの本当に良い例を見つけました。ToolTipPopupクラスは、アンカービューの上にツールチップを表示する単純なウィジェットクラスにすぎません。スクリーンショットを撮りました。
クラスは本当にシンプル(約200行)で、見る価値があります。そのクラスでは、WeakReference
クラスはアンカービューへの参照を保持するために使用されます。これは、ツールチップインスタンスがアンカービューよりも長く存続する場合でも、アンカービューがガベージコレクションされることを可能にするためです。
幸せなコーディング!:)
WeakReference
クラスの実用的な例を1つ紹介しましょう。これはと呼ばれるAndroidフレームワークウィジェットの小さなコードスニペットAutoCompleteTextView
です。
つまり、 この例でWeakReference
は 、クラスを使用してオブジェクトを保持View
し、メモリリークを防止しています。
のネストされたクラスであるPopupDataSetObserverクラスをコピーして貼り付けAutoCompleteTextView
ます。とてもシンプルで、コメントはクラスをよく説明しています。幸せなコーディング!:)
/**
* Static inner listener that keeps a WeakReference to the actual AutoCompleteTextView.
* <p>
* This way, if adapter has a longer life span than the View, we won't leak the View, instead
* we will just leak a small Observer with 1 field.
*/
private static class PopupDataSetObserver extends DataSetObserver {
private final WeakReference<AutoCompleteTextView> mViewReference;
private PopupDataSetObserver(AutoCompleteTextView view) {
mViewReference = new WeakReference<AutoCompleteTextView>(view);
}
@Override
public void onChanged() {
final AutoCompleteTextView textView = mViewReference.get();
if (textView != null && textView.mAdapter != null) {
// If the popup is not showing already, showing it will cause
// the list of data set observers attached to the adapter to
// change. We can't do it from here, because we are in the middle
// of iterating through the list of observers.
textView.post(updateRunnable);
}
}
private final Runnable updateRunnable = new Runnable() {
@Override
public void run() {
final AutoCompleteTextView textView = mViewReference.get();
if (textView == null) {
return;
}
final ListAdapter adapter = textView.mAdapter;
if (adapter == null) {
return;
}
textView.updateDropDownForFilter(adapter.getCount());
}
};
}
そして、PopupDataSetObserver
アダプタの設定で使用されています。
public <T extends ListAdapter & Filterable> void setAdapter(T adapter) {
if (mObserver == null) {
mObserver = new PopupDataSetObserver(this);
} else if (mAdapter != null) {
mAdapter.unregisterDataSetObserver(mObserver);
}
mAdapter = adapter;
if (mAdapter != null) {
//noinspection unchecked
mFilter = ((Filterable) mAdapter).getFilter();
adapter.registerDataSetObserver(mObserver);
} else {
mFilter = null;
}
mPopup.setAdapter(mAdapter);
}
最後に一つだけ。WeakReference
Androidアプリケーションの実際の例も知りたかったのですが、公式のサンプルアプリケーションでいくつかのサンプルを見つけることができました。しかし、私はそれらの使用法のいくつかを本当に理解することができませんでした。たとえば、ThreadSampleおよびDisplayingBitmapsアプリケーションはWeakReference
コードで使用しますが、いくつかのテストを実行した後null
、参照されたビューオブジェクトがガベージコレクションではなくアダプターでリサイクルされるため、get()メソッドがを返さないことがわかりました。
他の回答の一部は、不完全または長すぎるようです。これが一般的な答えです。
次の手順を実行できます。
WeakReference
変数を作成するMyClass
への弱い参照がありAnotherClass
ます。
public class MyClass {
// 1. Create a WeakReference variable
private WeakReference<AnotherClass> mAnotherClassReference;
// 2. Set the weak reference (nothing special about the method name)
void setWeakReference(AnotherClass anotherClass) {
mAnotherClassReference = new WeakReference<>(anotherClass);
}
// 3. Use the weak reference
void doSomething() {
AnotherClass anotherClass = mAnotherClassReference.get();
if (anotherClass == null) return;
// do something with anotherClass
}
}
AnotherClass
への強い参照がありMyClass
ます。
public class AnotherClass {
// strong reference
MyClass mMyClass;
// allow MyClass to get a weak reference to this class
void someMethod() {
mMyClass = new MyClass();
mMyClass.setWeakReference(this);
}
}
MyClass
は、Aでした。とAnotherClass
Bだった。WeakReference
別のクラスにインターフェースを実装させることもできます。これは、リスナー/オブザーバーパターンで行われます。// allow MyClass to get a weak reference to this class void someMethod() { mMyClass = new MyClass(); mMyClass.someMethod(this); }
ですか?
weakreference
、doSomething
関数内のオブジェクト自体がないことを確認する必要があります。null
get
「正規化された」マッピングでは、問題のオブジェクトの1つのインスタンスをメモリに保持し、他のすべてのインスタンスは、ポインターまたはそのようなメカニズムを介してその特定のインスタンスを検索します。これは、弱点参照が役立つ場所です。簡単に言えば、WeakReferenceオブジェクトを使用して、システム内のオブジェクトへのポインターを作成し、スコープ外に出たガベージコレクターがそれらのオブジェクトを再利用できるようにします。たとえば、次のようなコードがあるとします。
class Registry {
private Set registeredObjects = new HashSet();
public void register(Object object) {
registeredObjects.add( object );
}
}
のセットに格納されている参照があるため、登録したオブジェクトがGCによって再利用されることはありませんregisteredObjects
。一方、これを行うと:
class Registry {
private Set registeredObjects = new HashSet();
public void register(Object object) {
registeredObjects.add( new WeakReference(object) );
}
}
その後、GCがセット内のオブジェクトを再利用する場合、それを行うことができます。この手法は、キャッシング、カタログ作成などに使用できます。GCとキャッシングの詳細については、以下を参照してください。