Contextを理解する

27.4K Views

September 11, 24

スライド概要

profile-image

Android Developer

Docswellを使いましょう

(ダウンロード不可)

関連スライド

各ページのテキスト
1.

Contextを 理解する by Okumura DroidKaigi 2024

2.

Okumura X (Twitter) : @okmr_okok ● Androidエンジニア ● 合同会社DMM.com

3.

Context?

4.

例えば文字列リソースを取得するときの これ

5.

本セッションのゴール 以下がわかるようになること ● Contextとはなにか ● Contextの使い分け方 ● Contextを使う上での注意点

6.

本セッションの対象者 ● Android開発に興味がある方 ● Android開発初学者の方 ● Contextをなんとなく使っているという方

7.

Contextとは?

8.

Contextとは (訳) アプリケーション環境に関するグローバル情報へのインターフェース。 これは抽象クラスで、その実装は Androidシステムによって提供されます。 アプリケーション固有のリソースやクラスにアクセスできるほか、アクティビティの起動、インテントのブロード キャストや受信など、アプリケーションレベルの操作のアップコールも可能です。 出典:https://developer.android.com/reference/android/content/Context

9.

Contextとは アプリがアプリ内外の様々な情報や機能にアクセスするための窓口のようなもの アプリ Androidシステム Context アプリ情報 ・リソース ・テーマ ︙ ・システムサービス ・システム設定 ・ストレージ ︙

10.

Contextの使用例

11.

Contextの使用例 ● リソースへのアクセス ● 通知の作成 ● データベースへのアクセス etc… 他にもたくさんあります

12.

Contextってなんで必要なの?

13.

例1. 文字列リソースの取得 Contextがアプリケーションの現在の環境に基づいて 適切なリソースを提供

14.

例1. 文字列リソースの取得 ● res/values/strings.xml(デフォルトの言語用) ● res/values-en/strings.xml(英語用) ● res/values-es/strings.xml(スペイン語用)

15.

例1. 文字列リソースの取得

18.

Contextってなんで必要なの? 文字列リソースへのアクセスをする場合: ● 同じリソースIDでも端末のロケールによって返却される文字列 が変わる ● Contextが無いとどの言語の文字列を返せばよいかがわから ない

19.

例2. 通知の作成&表示 通知を作成する場合、Contextを通じて通知に必要なシステム サービス(NotificationManager)にアクセス Contextは通知のレイアウトやリソースの取得もサポートする

20.

例2. 通知の作成&表示 通知の表示までの流れ 1. 通知マネージャを取得 2. 通知チャンネルを作成 3. 通知を作成 4. 通知を表示

21.

例2. 通知の作成&表示

22.

例2. 通知の作成&表示

23.

例2. 通知の作成&表示

24.

例2. 通知の作成&表示

25.

Contextってなんで必要なの? 通知の作成&表示をする場合: ● Contextを通じてNotificationManagerにアクセスすること で、通知チャンネルの作成や通知の表示を実現 ● 通知を作成する際に必要なリソースを取得するためにも使わ れる

26.

Contextとは(再) アプリがアプリ内外の様々な情報や機能にアクセスするための窓口のようなもの アプリ Androidシステム Context アプリ情報 ・リソース ・テーマ ︙ ・システムサービス ・システム設定 ・ストレージ ︙

27.

Contextの種類と使い分け

28.

Contextの種類と使い分け そもそもContextは抽象クラス

29.

Contextの種類と使い分け 継承しているクラスは多くあるが、特に重要なものが2つ

30.

Contextの種類と使い分け 継承しているクラスは多くあるが、特に重要なものが2つ

31.

依存関係 Context ContextWrapper ContextThemeWrapper Application Activity

32.

Contextの種類と使い分け Activity(便宜上、以降は ActivityContext と記載) Activityのライフサイクルに依存 Application(便宜上、以降は ApplicationContext と記載) アプリのライフサイクルに依存

33.

Contextの種類と使い分け ActivityContext Activityのライフサイクルに依存 【用途】 ● Activityのライフサイクル内での短期的な処理 ● Activityの情報が必要な処理 ○ 例:Activityの起動、個別のActivityのテーマに紐づくUI要素の表示

34.

Contextの種類と使い分け ApplicationContext アプリのライフサイクルに依存 【用途】 ● Activityのライフサイクルを超えて行われる処理 ○ 例:Workerなどのバックグラウンド処理の起動、データベースへのアクセ ス

35.

誤ったContextを使うとどうなるの?

36.

Activityの情報が必要な処理でApplicationContextを使った場合 例:Activityを起動するケース

37.

Activityの情報が必要な処理でApplicationContextを使った場合 例:Activityを起動するケース クラッシュ

38.

Activityの情報が必要な処理でApplicationContextを使った場合 例:Activityを起動するケース (直訳)アクティビティ コンテキストの外部から startActivity() を呼び出すには、 FLAG_ACTIVITY_NEW_TASK フラグが必要です。これは本当にあなたが望むものですか?

39.

Activityのライフサイクルを超えて行われる処理でActivityContextを使った場合 例:Workerでバックグラウンドで処理を行うケース 【予想】Activity破棄後にContextにアクセスしようとしたときにク ラッシュする👀

40.

Activityのライフサイクルを超えて行われる処理でActivityContextを使った場合 例:Workerでバックグラウンドで処理を行うケース 【予想】Activity破棄後にContextにアクセスしようとしたときにク ラッシュする👀 【結果】せず!!!!!!

41.

Activityのライフサイクルを超えて行われる処理でActivityContextを使った場合 例:Workerでバックグラウンドで処理を行うケース 【予想】Activity破棄後にContextにアクセスしようとしたときにク ラッシュする👀 【結果】せず!!!!!! なんで??? ��

42.

Activityのライフサイクルを超えて行われる処理でActivityContextを使った場合 androidx.work.WorkManager#getInstance(android.content.Context) の中身見てみる

43.

Activityのライフサイクルを超えて行われる処理でActivityContextを使った場合 WorkManagerImplのgetInstanceメソッドに渡している WorkManagerImplのgetInstanceメソッドも見てみる

45.

内部でApplicationContext取得してた

46.

Activityのライフサイクルを超えて行われる処理でActivityContextを使った場合 ● 実際には、今回のようにActivityContextを渡してしまっても問 題ないケースもあるよう ● とはいえ全てのライブラリがそうとは限らないので、Activityの ライフサイクルを超える処理にはApplicationContextを使っ ておくのが無難(私の考え)

47.

メモリリーク

48.

メモリリークとは? ● メモリを必要以上に確保し続けることでメモリが無駄に消費さ れる現象 ● 他の処理に使えるメモリが減るのでアプリのパフォーマンスが 低下する

49.

ActivityContextがメモリリークを起こす例 Activityよりも寿命が長いViewModelでActivityContextのインスタンスを保持 警告が出る

50.

用途・ライフサイクルを意識して 正しいContextを選択しよう

51.

Contextの取得方法

52.

Contextの取得方法 ● AndroidView ○ Activity編 ○ Fragment編 ● JetpackCompose編

53.

AndroidView Activity編

54.

ActivityでのContextの取得方法 「this」で自身(ActivityContext)を取得

55.

ActivityでのContextの取得方法 applicationContextもそのまま取得できる

56.

AndroidView Fragment編

57.

【補足】Fragmentとは AndroidアプリのUIの一部を構成するためのコンポーネント Activityや他のFragmentによって動かされる Activity Fragment

58.

FragmentでのContextの取得方法 ● getContext() ● requireContext() ● getActivity() ● requireActivity()

59.

getXXXとrequireXXXの違い ● getContext() ● requireContext() ● getActivity() ● requireActivity()

60.

getXXXとrequireXXXの違い ● getContext、getActivity ○ Contextが存在しない場合はnullを返す ● requireContext、requireActivity ○ Contextが存在しない場合は例外 を吐く

61.

Contextが存在しないとは Fragment が Activity または他の Fragment に 結び付けられていない(アタッチされていない)状態

62.

どう使い分けたらいいのか

63.

どう使い分けたらいいのか アタッチされていることが確実な場合は requireXXX を使った方 が簡潔に書ける(わざわざ getXXX を使ってnullチェックをする必 要はない)

64.

アタッチされていることが確実なのは具体的にどういう場面?

65.

アタッチされていることが確実じゃない場合、どうしたらよいか 1. getXXX を使いnull チェックをする

66.

アタッチされていることが確実じゃない場合、どうしたらよいか 2. isAdded() によってアタッチされているかどうかを判定してか ら requireXXX を使う

67.

XXXContextとXXXActivityの違い ● getContext() ● requireContext() ● getActivity() ● requireActivity()

68.

XXXActivityとXXXContextの違い ● getActivity、requireActivity ○ Activity特有の機能にアクセスしたいとき ■ 例:Activityの起動、Activityに定義しているメソッドの呼び出し ● getContext、requireContext ○ Activityである必要がないとき

69.

FragmentでのContextの取得方法のまとめ XXXContext getXXX requireXXX getContext requireContext ● アタッチされていない可能性がある ● アタッチされていることが確実 ● Activity特有の機能にアクセスする必要 ● Activity特有の機能にアクセスする必要が がない XXXActivity getActivity ない requireActivity ● アタッチされていない可能性がある ● アタッチされていることが確実 ● Activity特有の機能にアクセスする必要 ● Activity特有の機能にアクセスする必要が がある ある

70.

JetpackCompose編

71.

Contextの取得方法(JetpackCompose) LocalContextを使用

72.

Contextの取得方法(JetpackCompose) ApplicationContextはこう

73.

LocalContextについて Compose の CompositionLocal という仕組みを使って現在の Context を提供

74.

LocalContextについて Compose の CompositionLocal という仕組みを使って現在の Context を提供 CompositionLocal はツリー構造の中で値を受け渡す仕組み で、自分で値をパスしていかなくてもLocalContext によって Context が自動的に渡され、どこでも使えるようになっている

75.

余談 JetpackComposeではフレームワークが Context を自動的に管理しているので Contextを指定する場面は従来よりも少ない Composable関数でのDialogの例 AndroidViewでのDialogの例

76.

ケーススタディ

77.

問題① ActivityContextを使用する適切なシナリオはどれですか? 1. アクティビティに依存する機能にアクセスする 2. アプリケーション全体で共有するリソースにアクセスする 3. バックグラウンド処理を行う

78.

答え ActivityContextを使用する適切なシナリオはどれですか? 1. アクティビティに依存する機能にアクセスする 2. アプリケーション全体で共有するリソースにアクセスする 3. バックグラウンド処理を行う

79.

問題② ActivityContextを使用する際にメモリリークを防ぐための適切な 方法はどれですか? 1. ActivityContextを短期間で使用し、長期間保持しない 2. ActivityContextをアプリケーション全体で共有する 3. ActivityContextを静的変数として保持する

80.

答え ActivityContextを使用する際にメモリリークを防ぐための適切な 方法はどれですか? 1. ActivityContextを短期間で使用し、長期間保持しない 2. ActivityContextをアプリケーション全体で共有する 3. ActivityContextを静的変数として保持する

81.

問題③ Fragmentがアタッチされていることが確実な場合、どのメソッドを 使ってContextにアクセスすべきですか? 1. requireContext() 2. getContext() 3. getApplicationContext() 4. LocalContext.current

82.

答え Fragmentがアタッチされていることが確実な場合、どのメソッドを 使ってContextにアクセスすべきですか? 1. requireContext() 2. getContext() 3. getApplicationContext() 4. LocalContext.current

83.

まとめ

84.

Contextとは(再々) アプリがアプリ内外の様々な情報や機能にアクセスするための窓口のようなもの アプリ Androidシステム Context アプリ情報 ・リソース ・テーマ ︙ ・システムサービス ・システム設定 ・ストレージ ︙

85.

ライフサイクルや役割を意識して 正しくContextを使っていきましょう!

86.

ありがとうございました