Android Contextの使い方

# 概要
何となくで使用していたContextについて学習をしました。
そのため、本ページにて学習した内容についてまとめます。

# この記事を見て理解できること
:::note info
**この記事を見て理解できること**
* AndroidのContextで出来ること
* contextの種類
* Fragmentで使用する際のcontextの取得方法
:::

# AndroidのContextで出来ること
AndroidにおけるContextの内容を展開

## そもそもContextってどういう意味？
一般的な意味合いとAndroidにおけるContextの意味合いは以下になります。

* <font color="#1e90ff">**一般的な意味合い**</font>：前後関係、文脈、脈絡、背景、状況、環境
* <font color="#1e90ff">**Androidにおける意味合い**</font>：同じコード記述やプログラム上の要素が、その置かれているプログラム内での位置や、実行される際の内部状態などによって異なる振る舞いをしたり、異なる制約を受けたりすること

## AndroidのContextで出来ること(詳細)
AndroidのContextでできる内容は多岐に渡ります。
下記はできることの例です。

* <font color="#1e90ff">**リソースのアクセス</font>**: レイアウトファイルや文字列リソースなど、アプリケーションのリソースにアクセスできる
* <font color="#1e90ff">**システムサービスの取得</font>**：システムサービス（例えば、通知マネージャーやカメラなど）にアクセスできる
* <font color="#1e90ff">**アプリケーションの起動</font>**：Intentを介して新しいアクティビティの開始や、アプリケーションの起動ができる

上記のできることのイメージとしては、以下になります。
![context_diagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677032/3c3620a0-386d-9260-353c-d9c7dc21f60c.png)

画像でも分かる通り、Contextはアプリ内外の情報や機能をアクセスするための架け橋となっています。

※Androidシステムで使用できる機能については、下記ページに全て記載されてます。
* [Context(Android Developers)](https://developer.android.com/reference/android/content/Context "Context(Android Developers)")

# Contextの種類
そもそもContextは抽象クラスになっています。
また、継承しているクラスは多く存在しているが、特に重要なものが以下2点になる。
　→この二つを使用する場面が多い。

1. ActiityのContext
1. ApplicationのContext

## Contextの継承について
ActivityのContextとApplicationのContextの継承については、下記画像にある通り、最終的に継承元が同じになります。
そのため、<font color="red">**取得できる内容は同じ**</font>になります。
　
![context.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677032/de2d0c55-4ead-b69b-76df-cc530870f038.png)

## Application ActivityのContextの違いについて
上記記載通り、取得できる内容に違いはないです。
そのため、どちらを使用するべきか悩むかと思います。(実際に最初にContextを使用した時は、どちらを使えばいいか悩んだ。)

どちらを使用するかについては、それぞれ依存内容が違うため、<font color="red">**使用用途によって使い分ける必要があります！！**</font>

### ActivityのContext
* **依存**：Activityのライフサイクルに依存
* **使用用途**：Activityのライフサイクル内での短期的な処理

### ApplicationのContext
* **依存**：アプリのライフサイクルに依存
* **使用用途**：Worker等のバックグラウンド処理で使用

上記二つの依存関係を理解して使用することが重要です。

:::note warn
**メモリリークについて**

Contextについては、使用方法を間違えるとメモリリークを引き起こすことがあります。

例：リスナーやコールバックの解除が行えていない

```kotlin
public class MyActivity extends Activity {
    private MyReceiver receiver = new MyReceiver();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        IntentFilter filter = new IntentFilter("SOME_ACTION");
        registerReceiver(receiver, filter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(receiver); // 解除を行わないとメモリリークの原因になる。
    }
}
```
:::

# Fragmentで使用する際のcontextの取得方法
FragmentでActivityのcontetを使用する方法は、下記4パターンあります。

* getContext()
* getActivity()
* requireContext()
* requireActivity()

また、require〇〇とget〇〇の違いはContextが存在しない場合のreturn値が異なります。

* **require〇〇の場合**：例外を吐く
* **get〇〇の場合**：nullを返す

〇〇Activityと〇〇Contextの違いは、取得できるContextの種類が違います。

* **〇〇Activityの場合**：ActivityのContextを取得できる
* **〇〇Contextの場合**：ApplicationのContextを取得できる

上記の事からまとめると以下になります。

|  | Contextがない場合の返り値 | 取得できるContextの種類 |
|:-----------|------------:|:------------:|
| getContext       |    null  | Application Context         |
| getActivity     | null      | Activity Context       |
| requireContext     | 例外      | Application Context       |
| requireActivity     | 例外      | Activity Context       |

:::note warn
**requireActivity()の使い方注意点**

ActivityのContextは`onAttach`の後から使用できて`onDetach`のタイミングで使用できなくなります。
そのため、バックグラウンド処理した内容を受け取りそれを基に処理などをする時に、require〇〇を読んでしまうと、既にDetach()されている可能性もあります。(通信が終わる前にFragmentが破棄されている等)
そのため、使用には注意が必要になります。
:::

これを加味するとget〇〇を使ってnullセーフな使い方をするのが無難です。

# 参考
* [コンテキスト 【context】 コンテクスト](https://e-words.jp/w/%E3%82%B3%E3%83%B3%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88.html "コンテキスト 【context】 コンテクスト")
* [Contextとは](https://www.docswell.com/s/Okumura/ZMXX92-understanding-context#p8　"Contextとは")
* [Context(Android Developers)](https://developer.android.com/reference/android/content/Context "Context(Android Developers)")
* [【Android】Context って何？？](https://qiita.com/tkmd35/items/e6abeed6ac68cbac09ed "【Android】Context って何？？")
* [Difference between getContext() and requireContext() when using fragments](https://stackoverflow.com/questions/60402490/difference-between-getcontext-and-requirecontext-when-using-fragments "Difference between getContext() and requireContext() when using fragments")