getApplication()とgetApplicationContext()の比較


417

私はこれに対する満足のいく答えを見つけることができなかったので、ここに行きます:何が対処されActivity/Service.getApplication()Context.getApplicationContext()

このアプリケーションでは、どちらも同じオブジェクトを返します。ではActivityTestCaseただし、アプリケーションをあざけることになりますgetApplication()モックで戻って来るが、getApplicationContextまだ別のコンテキストのインスタンス(アンドロイドによって注入1)を返します。それはバグですか?わざとですか?

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


8
いい質問です テストに関するものは、ちょっとした謎です(ご存じのとおり)。しかし、アプリでオブジェクトを明示的に作成しない場合、これらの2つのメソッド呼び出しに違いが現れるのではないかと思いApplicationます。
Christopher Orr

回答:


366

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

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

あなたがマニフェストに登録Applicationクラスをしたいのであれば、あなたがすべき決して呼び出しませんgetApplicationContext()、それはアプリケーションインスタンスではないかもしれないので、(あなたは明らかにテストフレームワークを経験している)、およびアプリケーションにキャスト。

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

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

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

Androidコードを見ると、アタッチされたときにアクティビティがベースコンテキストとアプリケーションを受け取り、それらは異なるパラメーターであることがわかります。getApplicationContext()それはへの呼び出しであるデリゲートbaseContext.getApplicationContext()

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

通常、サブクラス化する必要はありませんApplication。ほとんどの場合、静的シングルトンは、よりモジュール的な方法で同じ機能を提供できます。シングルトンにグローバルコンテキストが必要な場合(たとえば、ブロードキャストレシーバーを登録するため)、それを取得する関数に、最初にシングルトンを構築ContextするContext.getApplicationContext()ときに内部的に使用するを指定できます 。

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


89
@Piwaï:ドキュメントを聞かないでください。サブクラス化android.app.Applicationは非常に役立ちます。たとえば、データベースの初期化に際限のない問題がありました。Application.onCreateそこに移動すると、魅力のように機能しました。今私はすべてのシステム全体の初期化をApplication行い、それなしで別のアプリを書くことはありません。
マーティン

9
@Martinドキュメントをリッスンしないことは、一般に、コードが将来破損する可能性があることを意味します。または、現在でも予期しない状況で移植性が失われ、パフォーマンスが低下し、プラットフォーム開発者が有益な変更を行えないようにしますドキュメントではなく、現在の実装のみに基づいています)。これはかなり悪い行動であり、かなり悪いアドバイスです。
Palec、2014

17
@Palec:「通常、アプリケーションをサブクラス化する必要はありません。」—それは単なるヒントです。私はまだ正式に文書化された機能を意図した方法で使用しています。—最初はこれらの "静的シングルトン"を使用していましたが、それらはa…の苦痛であることが判明しました—遅延初期化には問題があります。特に計装テストで使用する場合。—モジュール化のためにこれらのシングルトンをまだ持っていますが、android.app.ApplicationサブクラスのonCreateでそれらをブロック化してインスタンス化します。—魅力のように機能します。
マーティン

9
@Martin私はそれを明確にすべきでした:私の反応は最初の文だけに関係していました。「ドキュメントを聞かないでください。」これは一般的に非常に危険なアドバイスです。しかし、「これは単なるヒントです。理由がある場合は、この場合は無視してかまいません。理由を示します...」というのは、まったく問題ありません。
Palec、2014

3
「ブロードキャストレシーバーでコンテキストではなく、onReceiveメソッドでコンテキストが指定されたコードを記述する場合、getApplicationContext()のみを呼び出すことができます。これは、BroadcastReceiverでアプリケーションにアクセスできることが保証されていないことも意味します。 」では、BroadcastReceiverのアプリケーションクラスにアクセスするにはどうすればよいでしょうか。
Dr.jacky 14

30

比較getApplication()getApplicationContext()

getApplication戻ってApplication次のようないくつかのデバイスの状況にあなたのグローバルなアプリケーションの状態と応答を管理できるようになりますオブジェクトonLowMemory()onConfigurationChanged()

getApplicationContextグローバルアプリケーションコンテキストを返します。他のコンテキストとの違いは、たとえば、アクティビティが終了すると、Androidによってアクティビティコンテキストが破棄される(または利用できなくなる)可能性があることです。アプリケーションコンテキストは、(特定のに関連付けられていない)アプリケーションオブジェクトが存在している間は常に使用可能なままなActivityので、これを使用して、より長期間、一時的なUIオブジェクトとは関係なく使用できるコンテキストを必要とする通知などに使用できます。

これらが同じであってもなくても、コードが何をしているかに依存すると思います-通常の使用では、それらは異なると思います。


19
しかしApplication であるContext(それはそれから継承)、および実行時に、両方の方法は、同じインスタンスを返します。違いは何ですか?
Matthias

3
違いはスコープです。アプリケーションが多数のアクティビティで構成されている場合でも、アクティビティはごく短時間しか使用されない可能性があるため、アプリケーションコンテキストは、たとえばアクティビティコンテキストよりもはるかに長く有効です。アクティビティコンテキストは、少なくとも最初のアクティビティが開始されたときに開始し、最後のアクティビティが終了したときに終了するまで有効です。それらはすべてコンテキストですが、1つはより長く持続し、変更されませんが、他は短命であり、インスタンスごとに異なるコンテキストを持つ場合があります。
RivieraKid

16
私の質問を誤解しているかもしれません。Activityコンテキストとコンテキストの違いを求めているのではありませんApplicationApplication(グローバルで一意のアプリケーションコンテキストである)と、何getApplicationContextが返されるかの違いを考えています。後者は実際にはAndroid 1.6以前は機能していませんでした。以前は常に戻ってきましたnull
Matthias

1
@Matthias私の意見ではそれはまだ関連しています。コンテキストはAndroidシステム自体によって挿入(実装)されますが、アプリケーションはコンテキストを継承および拡張します。アプリケーションクラスは簡単にモックできます(あなたが言ったように)。アプリケーションクラスが(テストプロジェクトで)何らかの "マジック"を実行して、おそらく注入されたコンテキストを無視することを示すのは安全な賭けではありませんか。
Audrius

3
また来てね?それが私の質問にどのように答えるかまだわかりません。
Matthias

30

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

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

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

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


「コンテキストはモックとプロキシをサポートする一般的な抽象概念です」と言うとき、正確に「プロキシ」とはどういう意味ですか?いくつかの参考資料を教えていただけますか?コンテキスト全体がかなり複雑になっています。
ティアゴ2015年

この答えは、あなたがよりよく理解するのに役立ちます@Tiago:stackoverflow.com/questions/10641144/...
スーパー

-13

質問に答えるために、getApplication()はApplicationオブジェクトを返し、getApplicationContext()はContextオブジェクトを返します。あなた自身の観察に基づいて、私は両方のコンテキストが同一であると仮定します(つまり、アプリケーションクラスが後者の関数を呼び出して基本クラスのコンテキスト部分を設定するか、または同等のアクションが実行されます)。コンテキストだけが必要な場合は、どの関数を呼び出すかは重要ではありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.