こんにちは、ふりいです。
デモアプリを作り始めて、疑問になっていた箇所がありました。
何かというと、コンテキスト(Context)というやつです。
日本語だと「文脈」とかになるんでしょうか。
今回は、そいつがいったい何者なのかを私なりに解説していきます。
Contents
参考コードと自己流コードを比較する
デモ作成にあたって、参考にしたコードがあったのですが、一部は私なりにアレンジしていました。
(そのままのコードだと、エラーが発生していたので)
ちなみに、デモ作成記事は以下となります。
「処理の中身を記述する」という段落が、実際に参考コードをアレンジしているところです。
≫参考:現役SEがゼロから作るAndroidアプリ構築【デモ作成①】
どうアレンジしたかというと、参考コードの中で、
MainActivity.java
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
こんな風に書かれていた箇所がありました。
ダイアログを作る際に最初に登場したコードです。
これに対して、私は、
MainActivity.java
AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext());
こう修正しました。
「getActivity()」を「view.getContext()」に変えたわけですね。
ここで疑問に思ったわけです。
(エラーだったから直したことは、まぁ良いとして)なんで引数(ひきすう)が必要なの、と。
ダイアログを作るだけなら、「new AlertDialog.Builder();」で良いのでは?ってことですね。
コンテキスト(Context)とは何か
この疑問を解消するために、コンテキスト(Context)という概念を知る必要がありました。
AlertDialog.Builderの引数が、Contextクラスになっていたからです。
Androidアプリ開発者向けの公式サイトには、このように書かれています。
Interface to global information about an application environment.
This is an abstract class whose implementation is provided by the Android system.
It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc.
≫参考:Context - Android Developers
英語は苦手。ただ、最初の1行くらいなら分かりそうです。
「アプリ環境についての全体的な情報へのインターフェース。」ですかね。
アプリに関する様々な要素(画面やデータ)へのアクセスを可能にしてくれるものでしょうね。
ここから考えてみると、Contextを使用する場合というのは、アプリ内の特定の要素へアクセスしたい時だと推測できます。
本題に戻ると、「ダイアログを作るためにアプリ内の要素へアクセスしたい、そのためにContextを使用する必要がある」のでしょう。
さらに考えてみると、確かにダイアログを作る際には、「どの画面に?」という情報が必要ですよね。
今回はひとつの画面だから「どの画面に?」は明確に決まっていましたが、もし画面を複数作ったら、どの画面上にダイアログを作ればいいか不明になりますね。
なので、画面との紐づけ情報としてContextを設定して、ダイアログを作るということでしょう。
Contextの種類について
私が今回使用したのは、ViewクラスのgetContextメソッドでした。
しかし、他にも似たような位置づけのものがあるようなので、その一部を紹介します。
ViewクラスのgetContextメソッド
今回実際にコードとして書いたメソッドです。
詳細について、公式サイトから説明を見ます。またもや英語ですが。
Returns the context the view is running in, through which it can access the current theme, resources, etc.
≫参考:View#getContext() - Android Developers
「そのviewが実行中となっているコンテキストを戻す」とありますね。
要は、今のview(見ている画面)のコンテキストを取得できるって感じでしょうか。
ContextクラスのgetApplicationContextメソッド
私が作業している途中にコード補完で、getApplicationContext()というメソッドが出てきました。
こちらもContextを返却するメソッドのようです。説明を確認します。
Return the context of the single, global Application object of the current process. This generally should only be used if you need a Context whose lifecycle is separate from the current context, that is tied to the lifetime of the process rather than the current component.
≫参考:Context#getApplicationContext() - Android Developers
「現在のプロセスの全体的なアプリオブジェクトのコンテキストを戻す」と訳せます。
わかったような、わからないような感じですね。
今使っているアプリ全体のコンテキストである、と理解することにします。
ContextWrapperクラスのgetBaseContextメソッド
そもそもWrapperって何だという人もいるはず。読み方は「ラッパー」です。
役割としては、おおもとの機能を含みつつ、+αとしての機能も持つといったところでしょう。
ContextWrapperクラスは、Contextクラスの機能を含みつつ、+αとして「あるコンテキストから、別のコンテキストにアクセスする」機能も持っているクラスのことです。
また、公式の説明には「元のコンテキストを変えることなく、動作を修正するようにサブクラス化できる」ともあります。元の機能は変えないで、+αを使えるようにできるよってことですかね。
以上を理解した上で、getBaseContextメソッドについて、
the base context as set by the constructor or setBaseContext
≫参考:ContextWrapper#getBaseContext() - Android Developers
このように書かれていますね。
単純に、ContextWrapperクラスのための(別のコンテキストにアクセスするための)基本的なコンテキストであると理解すれば問題なさそうです。
※constructorやsetBaseContextという単語が出てきますが、今回は深入りしないでおきます。
this(インスタンス変数)
最後に、何とかクラスの何とかメソッドではないものを紹介します。
それが「this」です。日本語で「これ・この」ですね。補足するなら「このインスタンス」です。
インスタンスとは簡単に言うなら、
・設計図を実体化したもの
・レシピ(=クラス)をもとに作った料理
というようなイメージ。
さらに噛み砕いて説明すると、「この=自分自身の」と言い換えることができます。
「今まさに処理が動いているクラス」というニュアンスが近いのかな。
よって、thisは「自分自身のインスタンス」、「今まさに処理が動いているクラスのインスタンス」というような意味になります。
今回のデモアプリの例で言うと、thisはMainActivityクラスのインスタンスを指します。
ちなみに、Activityもコンテキストの仲間なので、他のコンテキストと同様にAlertDialog.Builderの引数として使用できます。
Contextのまとめ
ここまで見てきたContextたちの特徴をまとめると以下の通りになります。
・getApplicationContext:今使っているアプリ全体のコンテキスト
・getBaseContext:別のコンテキストにアクセスするための基本的なコンテキスト
・this:自分自身のインスタンス(今回はMainActivityクラスのインスタンス)
実際にそれぞれのコンテキストで、ダイアログの作成を試みました。
すると、これらのうち、getContextとthisでは作成することができました。
一方で、getApplicationContextとgetBaseContextでは作成に失敗しました。
上記の特徴を前提にすると、ダイアログを作成できるか否かを決定する要因となるのは「画面を一意に特定できるか否か」であるように思います。
getContextは、画面に対応するコンテキストなので一意に決まりますね。
そしてthisは、MainAcitivityクラスのインスタンスです。
基本的にActivityと画面は、1対1となります。よって、thisでも一意に決まりそうです。
他の2つのメソッドは、画面を一意に特定することはできないだろうというのが私の理解です。
違っている場合もあるかもしれませんが、ひとまずこの理解で進めていこうと思います。
今回は以上です。
少しでも皆さんの参考になれば嬉しいです。
参考になりました。
I really like what you guys tend to be up too. This type of clever work and coverage! Keep up the fantastic works guys I’ve added you guys to blogroll.
とても参考になる記事を書いていただきありがとうございました。