これらの2つのコンテキストが何であるかについて、多くの投稿がありました。
私がこれまでのところ理解しているように、それぞれはそのクラスのインスタンスです。つまり、一部のプログラマーは、メモリを「リーク」させないために、できるだけthis.getApplicationContext()
を使用することをお勧めします。これは、他のthis
(Activity
インスタンスコンテキストを取得する)が、ユーザーが電話を傾けたりアプリを終了するたびに破棄されるActivity
を指すためです。ガベージコレクター(GC)はキャッチしないため、メモリが多すぎます。
しかし、this
(現在のActivity
インスタンスのコンテキストを取得する)を使用するのが適切であり、アプリケーションコンテキストが役に立たない/間違っている、本当に良いコーディング例を誰かが思い付くことができますか?
getApplicationContext()
はほとんどの場合間違っています。 Ms。Hackborn (とりわけ)あなたが知っているとき、あなたはonlygetApplicationContext()
を使用するwhygetApplicationContext()
を使用しており、getApplicationContext()
を使用する必要があるneedのみ。
率直に言って、「一部のプログラマー」はJavaの経験が限られているため、getApplicationContext()
(またはそれよりも少ない範囲でgetBaseContext()
)を使用しています。内部クラス(OnClickListener
のButton
のActivity
など)を実装し、Context
が必要です。 MyActivity.this
を使用して外部クラスのthis
を取得するのではなく、getApplicationContext()
またはgetBaseContext()
を使用してContext
オブジェクトを取得します。
あなたはonlygetApplicationContext()
を使用するのは、あなたがknowときにContext
が必要な場合あなたが自由に使える他のContext
よりも長生きするかもしれません。シナリオは次のとおりです。
グローバルなスコープを持つContext
に関連付けられたものが必要な場合は、getApplicationContext()
を使用します。サービスに使用される静的なWakefulIntentService
には、たとえばWakeLock
のgetApplicationContext()
を使用します。 WakeLock
は静的であり、Context
を作成するにはPowerManager
が必要なので、getApplicationContext()
を使用するのが最も安全です。
Service
からActivity
にバインドする場合、getApplicationContext()
を介してServiceConnection
インスタンス間でActivity
(つまり、バインディングへのハンドル)を渡す場合は、onRetainNonConfigurationInstance()
を使用します。 Androidは、これらのServiceConnections
を介して内部的にバインディングを追跡し、バインディングを作成するContexts
への参照を保持します。 Activity
からバインドする場合、新しいActivity
インスタンスは、古いServiceConnection
への暗黙的な参照を持つActivity
への参照を持ち、古いActivity
はガベージコレクションできません。
一部の開発者は、独自のグローバルデータに対してApplication
のカスタムサブクラスを使用し、getApplicationContext()
を介して取得します。それは確かに可能です。 oneカスタムApplication
オブジェクトのみを持つことができる以外の理由がない場合、静的データメンバーを好みます。カスタムApplication
オブジェクトを使用して1つのアプリを構築しましたが、それは苦痛でした。 ハックボーンさんもこの立場に同意します 。
どこにでもgetApplicationContext()
を使用する理由notは次のとおりです。
完全なContext
ではなく、Activity
が行うすべてをサポートしています。このContext
を使用して実行しようとするさまざまなことが失敗します ほとんどがGUIに関連 。
getApplicationContext()
からのContext
が、クリーンアップしていない呼び出しによって作成されたものを保持している場合、メモリリークが発生する可能性があります。 Activity
を使用すると、何かを保持している場合、Activity
がガベージコレクションを取得すると、他のすべてもフラッシュされます。 Application
オブジェクトは、プロセスの存続期間中保持されます。
SDKのサイトにはドキュメントが不十分なものがたくさんあると思いますが、これもその1つです。主張するのは、デフォルトではアプリケーションコンテキストを使用し、本当に必要な場合にのみアクティビティコンテキストを使用する方が良いと思われるということです。アクティビティコンテキストが必要だと私が見た唯一の場所は、進行状況ダイアログです。 SBERG412は、トーストメッセージにはアクティビティコンテキストを使用する必要があると主張していますが、Androidドキュメントには、使用されているアプリケーションコンテキストが明確に示されています。このGoogleの例のため、トーストには常にアプリケーションコンテキストを使用しています。間違っている場合、Googleはここでボールをドロップしました。
考えて確認することは次のとおりです。
トーストメッセージの場合、Google Dev Guideはアプリケーションコンテキストを使用し、明示的にそれを使用するように言います: Toast Notifications
開発ガイドのダイアログセクションで、AlertDialog.Builderがアプリケーションコンテキストを使用し、プログレスバーがアクティビティコンテキストを使用していることがわかります。これはGoogleでは説明されていません。 ダイアログ
アプリケーションコンテキストを使用する適切な理由は、向きの変更などの構成の変更を処理し、Viewsなどのコンテキストを必要とするオブジェクトを保持する場合です。ここを見ると: Run Time Changes アクティビティコンテキストの使用には注意が必要です。これにより、リークが発生する可能性があります。これは、保持されるビューを持つアプリケーションコンテキストを使用することで回避できます(少なくとも私の理解では)。私が書いているアプリでは、向きの変更でいくつかのビューやその他のものを保持しようとしているので、アプリケーションのコンテキストを使用します。したがって、メモリリークを引き起こさないためにアプリコンテキストを使用する必要があります( メモリリークの回避 を参照)。私には、アクティビティコンテキストの代わりにアプリケーションコンテキストを使用するのに十分な理由があるように思われます。また、アクティビティコンテキストよりも頻繁に使用するように思えます。それが、私がこれまでに経験したAndroid本の多くがしているように見えることであり、それは私が見たGoogleの例の多くがしていることです。
Googleのドキュメントを見ると、ほとんどの場合、アプリケーションコンテキストを使用することはまったく問題ないように見えますが、実際には、例(少なくとも私が見た例)ではアクティビティコンテキストを使用するよりも頻繁に表示されます。アプリケーションコンテキストを使用するのが本当にこのような問題である場合、Googleはこれをさらに重視する必要があります。彼らはそれを明確にする必要があり、彼らの例をいくつかやり直す必要があります。権限(Google)がアプリケーションコンテキストを使用することは問題ではないように見えるので、私はこれを経験の浅い開発者に完全に非難しません。
このテーブルは、アプリケーションコンテキスト(すなわち:getApplicationContext()
)およびactivity context、またBroadcastReceiver context:
すべてのメリットは、元の著者 here に渡されます。
使用するコンテキストは?
コンテキストには2つのタイプがあります。
アプリケーションコンテキストはアプリケーションに関連付けられており、アプリケーションの存続期間を通じて常に同じであり、変更されません。したがって、Toastを使用している場合は、アプリケーションコンテキストまたはアクティビティコンテキスト(両方)を使用できます。トーストはアプリケーション内のどこからでも表示でき、特定のウィンドウにアタッチされていないためです。ただし、多くの例外があります。1つの例外は、アクティビティコンテキストを使用または渡す必要がある場合です。
アクティビティコンテキストはアクティビティに関連付けられており、アクティビティが破棄されると破棄される可能性があります-単一の応用。また、アクティビティコンテキストハンドルが絶対に必要な場合もあります。たとえば、新しいアクティビティを起動する場合、そのアクティビティコンテキストでアクティビティコンテキストを使用して、新しい起動アクティビティがアクティビティスタックに関して現在のアクティビティに接続されるようにする必要があります。ただし、アプリケーションのコンテキストを使用して新しいアクティビティを起動することもできますが、それを目的としてフラグIntent.FLAG_ACTIVITY_NEW_TASK
を設定して、新しいタスクとして扱う必要があります。
いくつかのケースを考えてみましょう。
MainActivity.this
は、Activityクラスを拡張するMainActivityコンテキストを指しますが、基本クラス(アクティビティ)はContextクラスも拡張するため、アクティビティコンテキストを提供するために使用できます。
getBaseContext()
はアクティビティコンテキストを提供します。
getApplication()
は、アプリケーションコンテキストを提供します。
getApplicationContext()
は、アプリケーションコンテキストも提供します。
詳細については、これを確認してください link 。
サポートするすべての操作にApplication Contextを使用しないのはなぜかと思っていました。最終的に、getContext()またはgetActivity()のメモリリークとnullチェックの欠落の可能性を低くします(注入されたアプリケーションコンテキストを使用する場合、またはApplicationから静的メソッドを介して取得する場合)。 Ms。Hackborn によるような、必要な場合にのみアプリケーションコンテキストを使用するステートメントは、理由の説明なしに私を納得させないように思われます。しかし、それは私が理由を疑っていないようだ:
一部のAndroidバージョン/デバイスの組み合わせにこれらのルールに従わない問題があることを発見しました。たとえば、コンテキストが渡されるBroadcastReceiverがあり、そのコンテキストをアプリケーションコンテキストに変換してから、アプリケーションコンテキストでregisterReceiver()を呼び出そうとすると、これがうまく機能する多くのインスタンスがありますが、 ReceiverCallNotAllowedExceptionによるクラッシュ。これらのクラッシュは、API 15から22までのさまざまなAndroidバージョンで発生します。 https://possiblemobile.com/2013/06/context/#comment-244328315
下の表のアプリケーションコンテキストでサポートされていると説明されているすべての操作が、すべてのAndroidデバイスで機能することは保証されないためです!-
アクティビティコンテキストとアプリケーションコンテキストを使用する必要がある2つの優れた例は、アプリケーションコンテキストを使用すると例外が発生するため、Toastメッセージまたは組み込みのダイアログメッセージを表示する場合です。
ProgressDialog.show(this, ....);
または
Toast t = Toast.makeText(this,....);
これらは両方とも、アプリケーションコンテキストでは提供されないアクティビティコンテキストからの情報を必要とします。
アプリケーションコンテキストliveアプリケーションが生きるまで、依存しないアクティビティライフサイクルではありますが、コンテキストオブジェクトを長持ちさせます。一時的に使用されるオブジェクトの場合は、その時点でApplication ContextおよびActivity ContextがApplication Contextの反対側で使用されます。