web-dev-qa-db-ja.com

getApplication()とgetApplicationContext()

私はこれに対する満足のいく答えを見つけることができませんでした、それではここに行きます:Activity/Service.getApplication()Context.getApplicationContext()の取り引きは何ですか?

我々のアプリケーションでは、どちらも同じオブジェクトを返します。ただし、ActivityTestCaseでは、アプリケーションをモックするとgetApplication()がモックで戻ってきますが、getApplicationContextは依然として別のコンテキストインスタンス(Androidによって挿入されたもの)を返します。それはバグですか?それは故意ですか?

そもそも違いが分からない。テストスイート以外で、両方の呼び出しで異なるオブジェクトが返される場合がありますか?いつそしてなぜ?さらに、なぜgetApplicationActivityServiceに定義されていて、Contextには定義されていないのですか。 anywhereから利用できる有効なアプリケーションインスタンスが常に存在するべきではありませんか?

394
Matthias

非常に興味深い質問です。私はそれが主に意味的な意味であると思います、そしてまた歴史的な理由によるかもしれません。

現在のAndroidのActivity and Serviceの実装では、getApplication()getApplicationContext()は同じオブジェクトを返しますが、これが常に当てはまるという保証はありません(たとえば、特定のベンダーの実装で)。

つまり、マニフェストに登録したApplicationクラスが必要な場合は、 never getApplicationContext()に呼び出してアプリケーションにキャストする必要があります。これはアプリケーションインスタンスではない可能性があるためです(テストフレームワークで明らかに経験しました)。

なぜgetApplicationContext()がそもそも存在するのですか?

getApplication()はActivityクラスとServiceクラスでのみ使用できますが、getApplicationContext()はContextクラスで宣言されています。

これは実際には1つのことを意味します。ブロードキャストレシーバでコードを書くとき、それはコンテキストではありませんが、onReceiveメソッドでコンテキストが与えられている場合は、getApplicationContext()しか呼び出せません。これはまたBroadcastReceiverであなたのアプリケーションにアクセスすることが保証されていないことを意味します。

Androidコードを見ると、添付されているときに、アクティビティは基本コンテキストとアプリケーションを受け取りますが、これらは異なるパラメーターです。 getApplicationContext()baseContext.getApplicationContext()への呼び出しを委任します。

もう1つ:ドキュメントには、ほとんどの場合、Applicationをサブクラス化する必要はないと記載されています。

Applicationをサブクラス化する必要は通常ありません。ほとんどの場合、スタティックシングルトンはより機能的な方法で同じ機能を提供できます。シングルトンがグローバルなコンテキストを必要とする場合(例えば、放送受信機を登録するため)、それを検索する関数は、シングルトンを最初に構築するときに内部的にContext.getApplicationContext()を使用するContextを与えることができます。

これは正確で正確な答えではないことを私は知っていますが、それでも、それはあなたの質問に答えますか?

350

getApplication()getApplicationContext() を比較してください。

getApplicationApplication オブジェクトを返します。これにより、グローバルアプリケーションの状態を管理し、 onLowMemory()onConfigurationChanged() などのデバイスの状況に対応できます。

getApplicationContextはグローバルアプリケーションコンテキストを返します - 他のコンテキストとの違いは、例えば、アクティビティが終了したときにAndroidによってアクティビティコンテキストが破壊される(あるいは利用不可能になる)可能性があることです。 Applicationオブジェクトは、(特定のActivityに結び付けられていない)存在している間ずっと利用可能なままであるので、 Notifications のような、より長い期間利用可能で独立したコンテキストを必要とするものに使用できます。一時的なUIオブジェクト.

私はそれがあなたのコードが何をしているかどうかに依存していると思います - これらが同じであろうとなかろうと - 私はそれらが違うと期待しますが。

30
RivieraKid

コンテキストラッピングと関係があるようです。 Context から派生したほとんどのクラスは実際には ContextWrapper であり、これは基本的に別のコンテキストに委譲されており、おそらくラッパーによって変更されています。

コンテキストは、モッキングとプロキシをサポートする一般的な抽象概念です。多くのコンテキストは Activity のような寿命の限られたオブジェクトに束縛されているので、将来の通知のための登録などの目的のために、より長命のコンテキストを取得する方法が必要です。それは Context.getApplicationContext() によって達成されます。論理的な実装はグローバルな Application オブジェクトを返すことですが、コンテキスト実装が代わりに適切な有効期間を持つラッパーまたはプロキシを返すことを妨げるものはありません。

アクティビティとサービスは、 Application オブジェクトとより具体的に関連付けられています。これの有用性は、Applicationから派生したカスタムクラスをマニフェストに作成して登録でき、 Activity.getApplication() または Service.getApplication() がその特定の型の特定のオブジェクトを返すことを確実にすることですあなたはあなたの派生Applicationクラスにキャストして、どんなカスタム目的のためにでも使うことができます。

つまり、getApplication()Applicationオブジェクトを返すことが保証されていますが、getApplicationContext()は代わりにプロキシを自由に返すことができます。

29
usethe4ce