web-dev-qa-db-ja.com

GetContext()、getApplicationContext()、getBaseContext()、および "this"の違い

getContext()getApplicationContext()getBaseContext()、および "this"の違いは何ですか?

これは簡単な質問ですが、基本的な違いはわかりません。可能であればいくつかの簡単な例を挙げてください。

504
iCurious
  • View.getContext() :ビューが現在実行されているコンテキストを返します。通常は現在アクティブなActivityです。

  • Activity.getApplicationContext() :アプリケーション全体のコンテキスト(すべてのアクティビティが内部で実行されているプロセス)を返します。現在のActivityだけでなく、アプリケーション全体のライフサイクルに関連したコンテキストが必要な場合は、現在のActivityコンテキストの代わりにこれを使用してください。

  • ContextWrapper.getBaseContext() :他のコンテキスト内からコンテキストへのアクセスが必要な場合は、ContextWrapperを使います。そのContextWrapperの内側から参照されるContextはgetBaseContext()を通してアクセスされます。

495
Alexander Lucas

ほとんどの回答はすでにgetContext()getApplicationContext()をカバーしていますが、 getBaseContext() はほとんど説明されていません。

メソッドgetBaseContext()は、あなたがContextWrappername__を持っている場合にのみ関係します。 Androidは、既存のContextWrappername__を中心に作成されたContextname__クラスを提供します。

ContextWrapper wrapper = new ContextWrapper(context);

ContextWrappername__を使用する利点は、「元のコンテキストを変更せずに動作を変更できる」ということです。たとえば、myActivityname__というアクティビティがある場合、Viewname__とは異なるテーマでmyActivityname__を作成できます。

ContextWrapper customTheme = new ContextWrapper(myActivity) {
  @Override
  public Resources.Theme getTheme() { 
    return someTheme;
  }
}
View myView = new MyView(customTheme);

ContextWrappername__は、リソースにアクセスするためのコード(openFileInput()getString()など)を含むContextname__によって提供されるほとんどの関数をオーバーライドし、他のコンポーネントと対話し(例えばsendBroadcast()registerReceiver())、許可を要求し(例えばcheckCallingOrSelfPermission())、ファイルシステムの場所(例えば) getFilesDir())。 ContextWrappername__は、デバイス/バージョン固有の問題を回避したり、ビューなどのコンテキストを必要とするコンポーネントに個別のカスタマイズを適用したりするのに非常に便利です。

メソッド getBaseContext() を使用すると、ContextWrappername__がラップアラウンドする「ベース」コンテキストにアクセスできます。必要に応じて、「ベース」コンテキストにアクセスする必要があります。たとえば、それがServicename__、Activityname__、またはApplicationname__であるかどうかを確認します。

public class CustomToast {
  public void makeText(Context context, int resId, int duration) {
    while (context instanceof ContextWrapper) {
      context = context.baseContext();
    }
    if (context instanceof Service)) {
      throw new RuntimeException("Cannot call this from a service");
    }
    ...
  }
}

あるいは、ラップされていないバージョンのメソッドを呼び出す必要がある場合は、次のようにします。

class MyCustomWrapper extends ContextWrapper {
  @Override
  public Drawable getWallpaper() {
    if (BuildInfo.DEBUG) {
      return mDebugBackground;
    } else {
      return getBaseContext().getWallpaper();
    }
  }
}
70
Mike Laren

getApplicationContext() - アプリケーションで実行されているすべてのアクティビティのコンテキストを返します。

getBaseContext() - アプリケーション内の別のコンテキストからContextにアクセスする場合は、アクセスできます。

getContext() - コンテキストビューのみを現在実行中のアクティビティとして返します。

38
Jay Patel

Contextは、新しく作成されたコンポーネントにActvityまたはApplicationに関する情報を提供します。

関連するContextは新しく作成されたコンポーネントに提供されるべきです(アプリケーションコンテキストかアクティビティコンテキストかにかかわらず)

ActivityContextのサブクラスなので、そのアクティビティのコンテキストを取得するためにthisを使うことができます。

28
tez

「コンテキストとは何か」という質問は、Androidの世界で最も難しい質問の1つです。

コンテキストは、システムリソースへのアクセス、アプリケーションの静的アセットの取得、権限の確認、UI操作の実行などを行うメソッドを定義します。本質的に、Contextは生産におけるゴッドオブジェクトアンチパターンの例です。

どの種類のContextを使うべきかということになると、それは非常に複雑になります。なぜなら、Contextサブクラスの階層ツリーは、神オブジェクトであることを除いて、残念ながらLiskov Substitution Principleに違反するからです。

このブログ記事 はさまざまな状況でのContextクラスの適用性を要約しようとしています。

完全を期すためにその記事のメインテーブルをコピーしてみましょう。

+----------------------------+-------------+----------+---------+-----------------+-------------------+
|                            | Application | Activity | Service | ContentProvider | BroadcastReceiver |
+----------------------------+-------------+----------+---------+-----------------+-------------------+
| Show a Dialog              | NO          | YES      | NO      | NO              | NO                |
| Start an Activity          | NO¹         | YES      | NO¹     | NO¹             | NO¹               |
| Layout Inflation           | NO²         | YES      | NO²     | NO²             | NO²               |
| Start a Service            | YES         | YES      | YES     | YES             | YES               |
| Bind to a Service          | YES         | YES      | YES     | YES             | NO                |
| Send a Broadcast           | YES         | YES      | YES     | YES             | YES               |
| Register BroadcastReceiver | YES         | YES      | YES     | YES             | NO³               |
| Load Resource Values       | YES         | YES      | YES     | YES             | YES               |
+----------------------------+-------------+----------+---------+-----------------+-------------------+
  1. アプリケーションはここからアクティビティを開始できますが、新しいタスクを作成する必要があります。これは特定のユースケースに合うかもしれませんが、あなたのアプリケーションの中で非標準のバックスタックの振る舞いを作り出すことができます、そして、一般的にはお勧めできないか、良い習慣と考えられません。
  2. これは有効ですが、インフレーションはアプリケーションで定義されているものではなく、実行しているシステムのデフォルトテーマで行われます。
  3. Android 4.2以降で、受信側がnullの場合、許可されます。これは、スティッキーブロードキャストの現在の値を取得するために使用されます。

screenshot

19
Vasiliy

コンテキストのUML図の一部

enter image description here

8
yoAlex5

これから docs

私はあなたが使うべきだと理解しました:

Context-activityの代わりにcontext-applicationを使ってみてください

1
mehmet

getApplicationContext()

これはアプリケーションレベルで使用され、すべてのアクティビティを指します。

getContext()およびgetBaseContext()

たぶん同じである。これらは生きている現在の活動だけに依存している。

この

常に現在のクラスオブジェクトを参照します。

0
Jatin Bansal