web-dev-qa-db-ja.com

アクティビティコンテキストORアプリケーションコンテキストを呼び出すタイミング

これらの2つのコンテキストが何であるかについて、多くの投稿がありました。

私がこれまでのところ理解しているように、それぞれはそのクラスのインスタンスです。つまり、一部のプログラマーは、メモリを「リーク」させないために、できるだけthis.getApplicationContext()を使用することをお勧めします。これは、他のthisActivityインスタンスコンテキストを取得する)が、ユーザーが電話を傾けたりアプリを終了するたびに破棄されるActivityを指すためです。ガベージコレクター(GC)はキャッチしないため、メモリが多すぎます。

しかし、this(現在のActivityインスタンスのコンテキストを取得する)を使用するのが適切であり、アプリケーションコンテキストが役に立たない/間違っている、本当に良いコーディング例を誰かが思い付くことができますか?

251
Norfeldt

getApplicationContext()はほとんどの場合間違っています。 Ms。Hackborn (とりわけ)あなたが知っているとき、あなたはonlygetApplicationContext()を使用するwhygetApplicationContext()を使用しており、getApplicationContext()を使用する必要があるneedのみ。

率直に言って、「一部のプログラマー」はJavaの経験が限られているため、getApplicationContext()(またはそれよりも少ない範囲でgetBaseContext())を使用しています。内部クラス(OnClickListenerButtonActivityなど)を実装し、Contextが必要です。 MyActivity.thisを使用して外部クラスのthisを取得するのではなく、getApplicationContext()またはgetBaseContext()を使用してContextオブジェクトを取得します。

あなたはonlygetApplicationContext()を使用するのは、あなたがknowときにContextが必要な場合あなたが自由に使える他のContextよりも長生きするかもしれません。シナリオは次のとおりです。

  • グローバルなスコープを持つContextに関連付けられたものが必要な場合は、getApplicationContext()を使用します。サービスに使用される静的なWakefulIntentServiceには、たとえばWakeLockgetApplicationContext()を使用します。 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オブジェクトは、プロセスの存続期間中保持されます。

389
CommonsWare

SDKのサイトにはドキュメントが不十分なものがたくさんあると思いますが、これもその1つです。主張するのは、デフォルトではアプリケーションコンテキストを使用し、本当に必要な場合にのみアクティビティコンテキストを使用する方が良いと思われるということです。アクティビティコンテキストが必要だと私が見た唯一の場所は、進行状況ダイアログです。 SBERG412は、トーストメッセージにはアクティビティコンテキストを使用する必要があると主張していますが、Androidドキュメントには、使用されているアプリケーションコンテキストが明確に示されています。このGoogleの例のため、トーストには常にアプリケーションコンテキストを使用しています。間違っている場合、Googleはここでボールをドロップしました。

考えて確認することは次のとおりです。

トーストメッセージの場合、Google Dev Guideはアプリケーションコンテキストを使用し、明示的にそれを使用するように言います: Toast Notifications

開発ガイドのダイアログセクションで、AlertDialog.Builderがアプリケーションコンテキストを使用し、プログレスバーがアクティビティコンテキストを使用していることがわかります。これはGoogleでは説明されていません。 ダイアログ

アプリケーションコンテキストを使用する適切な理由は、向きの変更などの構成の変更を処理し、Viewsなどのコンテキストを必要とするオブジェクトを保持する場合です。ここを見ると: Run Time Changes アクティビティコンテキストの使用には注意が必要です。これにより、リークが発生する可能性があります。これは、保持されるビューを持つアプリケーションコンテキストを使用することで回避できます(少なくとも私の理解では)。私が書いているアプリでは、向きの変更でいくつかのビューやその他のものを保持しようとしているので、アプリケーションのコンテキストを使用します。したがって、メモリリークを引き起こさないためにアプリコンテキストを使用する必要があります( メモリリークの回避 を参照)。私には、アクティビティコンテキストの代わりにアプリケーションコンテキストを使用するのに十分な理由があるように思われます。また、アクティビティコンテキストよりも頻繁に使用するように思えます。それが、私がこれまでに経験したAndroid本の多くがしているように見えることであり、それは私が見たGoogleの例の多くがしていることです。

Googleのドキュメントを見ると、ほとんどの場合、アプリケーションコンテキストを使用することはまったく問題ないように見えますが、実際には、例(少なくとも私が見た例)ではアクティビティコンテキストを使用するよりも頻繁に表示されます。アプリケーションコンテキストを使用するのが本当にこのような問題である場合、Googleはこれをさらに重視する必要があります。彼らはそれを明確にする必要があり、彼らの例をいくつかやり直す必要があります。権限(Google)がアプリケーションコンテキストを使用することは問題ではないように見えるので、私はこれを経験の浅い開発者に完全に非難しません。

47
Andi Jay

このテーブルは、アプリケーションコンテキスト(すなわち:getApplicationContext())およびactivity context、またBroadcastReceiver context

enter image description here

すべてのメリットは、元の著者 here に渡されます。

35
CommonSenseCode

使用するコンテキストは?

コンテキストには2つのタイプがあります。

  1. アプリケーションコンテキストはアプリケーションに関連付けられており、アプリケーションの存続期間を通じて常に同じであり、変更されません。したがって、Toastを使用している場合は、アプリケーションコンテキストまたはアクティビティコンテキスト(両方)を使用できます。トーストはアプリケーション内のどこからでも表示でき、特定のウィンドウにアタッチされていないためです。ただし、多くの例外があります。1つの例外は、アクティビティコンテキストを使用または渡す必要がある場合です。

  2. アクティビティコンテキストはアクティビティに関連付けられており、アクティビティが破棄されると破棄される可能性があります-単一の応用。また、アクティビティコンテキストハンドルが絶対に必要な場合もあります。たとえば、新しいアクティビティを起動する場合、そのアクティビティコンテキストでアクティビティコンテキストを使用して、新しい起動アクティビティがアクティビティスタックに関して現在のアクティビティに接続されるようにする必要があります。ただし、アプリケーションのコンテキストを使用して新しいアクティビティを起動することもできますが、それを目的としてフラグIntent.FLAG_ACTIVITY_NEW_TASKを設定して、新しいタスクとして扱う必要があります。

いくつかのケースを考えてみましょう。

  • MainActivity.thisは、Activityクラスを拡張するMainActivityコンテキストを指しますが、基本クラス(アクティビティ)はContextクラスも拡張するため、アクティビティコンテキストを提供するために使用できます。

  • getBaseContext()はアクティビティコンテキストを提供します。

  • getApplication()は、アプリケーションコンテキストを提供します。

  • getApplicationContext()は、アプリケーションコンテキストも提供します。

詳細については、これを確認してください link

11
Zohra Khan

サポートするすべての操作に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デバイスで機能することは保証されないためです!- enter image description here

4
Malachiasz

アクティビティコンテキストとアプリケーションコンテキストを使用する必要がある2つの優れた例は、アプリケーションコンテキストを使用すると例外が発生するため、Toastメッセージまたは組み込みのダイアログメッセージを表示する場合です。

ProgressDialog.show(this, ....);

または

Toast t = Toast.makeText(this,....);

これらは両方とも、アプリケーションコンテキストでは提供されないアクティビティコンテキストからの情報を必要とします。

3
SBerg413

アプリケーションコンテキストliveアプリケーションが生きるまで、依存しないアクティビティライフサイクルではありますが、コンテキストオブジェクトを長持ちさせます。一時的に使用されるオブジェクトの場合は、その時点でApplication ContextおよびActivity ContextがApplication Contextの反対側で使用されます。

3
Ganesh Katikar