Androidプログラミングについて全体を傍観する
ウォーキングデッドの第六シーズンの第3話で最初からずっと仲間として活躍してきたあの人が死んじゃってとっても悲しいpooh3です。><..
今日は、全然ウォーキングデッドと関係ないですけどw
俺プログラマーだけどAndroid勉強してアプリ出してみたい!って人のための記事です。
以前も似た様な記事は書いたのですが、改めて先日、C#が得意だけどAndroidやったことない
という外注さんにAndroidについて簡単なレクチャーすることがあったので、ここで再度まとめます。
Activity/Fragmentについて
イベントドリブン
Androidは基本的にイベントドリブンといって、何かを契機に開発者が実装したプログラムが実行できるようにプログラミングします。
イベントとはシステムがアプリを動作させ、ActivityやFragmentをフレームワーク側で呼び出して処理をさせる際、システム側からアプリのActivityやFragmentへ、通知を送ります。システム側からの通知をイベントといいます。イベントは、例えば
- 「表示するUIのレイアウトを読み込み、レイアウトと操作されるUIを紐付ける」
- 「UIを呼び出し、配置する処理を行う」
- 「配置したUIをレンダリング開始する」
といったような時に呼び出され、各箇所で
必要な処理の実装を行うことで、アプリの動作を決定させます。
ライフサイクル
特に、システムに呼び出されたActivityやFragmentが実行される時によく使われるイベントをライフサイクルイベントといい、ActivityやFragmentが表示される段階で今どんな状態にあるのかをそのイベントによって知ることができます。
ActivityやFragmentの状態では、例えばこれからUIの表示を操作するのに適切ではない時や、他の画面から復帰した時画面の表示が一旦停止したり、画面その物が破棄される時などを知ることができます。
ですので、どの状態でどういう操作をすればいいのかを、そのライフサイクルのイベントの特性から考え、どのイベントではどんな処理を
しなければならないのか、どういう処理がそこでは適切なのかを知ることがとても重要です。
例えば画面が破棄されている時に、通信の結果をその画面で表示しようとすると、UIへの参照が破棄されていてNullPointerの例外でアプリが落ちてしまうように、その時には相応しくない処理や、逆にその時には他のイベントよりよほど相応しいという処理があるのです。
Androidのアプリの基本構成
Androidのアプリを構成するものは基本的に画像などのリソース、画面構成を定義するレイアウト、そしてそれらを表示させる土台となるActivityやFragmentといったものがあります。
ActivityやFragmentはアプリの画面単位の構成を司ることが多く、ライフサイクルイベントでレイアウトや画像を呼び出し、それらを組み合わせたUIの描画処理までの流れや、描画の中断、終了時の操作を担っています。
またマニフェストと言って、アプリがインストールされる時、そのアプリがどんなアプリなのかをシステムに教えておくために、システムに渡す最低限の情報を格納するドキュメントが存在します。
またそれ以外にも開発者はプログラミング言語のJavaと同等の動作として、アプリにデータをもたせたり、複雑な動作をさせたり、簡単に複数の画面を生成できるといったような、オブジェクト指向を使い、AndroidSDKで提供されるAPIを使ったプログラムを配置することで、GPSで現在地を取得したり、端末の傾きや、方位、通信やDB検索、カメラ撮影や動画再生など、多様な振る舞いをさせることができます。
タッチイベントでの処理
ボタンやリストをタップされた際、画面遷移や表示させる情報を変更させるなどといった操作が可能です。これによって、ユーザがアプリの動作を制御でき、ユーザが登録した情報を保存したり、ユーザが選択した情報をネットから取得し、表示するといった動作が可能になります。
アプリの設計について
アプリを作る際にはAndroidは基本的にActivityやFragmentのライフサイクルイベントを使って、表示させるレイアウトや、表示させる情報を設定する必要があります。その際に、より効率的なプログラム構成になるようにオブジェクト指向を使った設計を行います。
アプリを効率的に作成する。その目的のためにJava言語とAndroidSDKのAPIを利用した実装への設計が必要になります。そして同様な処理を直感的かつ簡単に一つまとめたり、複数の情報の塊を作成できるようにするのがオブジェクト指向言語です。
オブジェクト志向言語には多くの実践パターンが存在しており、そのパターンを使うことで、設計コストを下げ、処理の共通化を図り、より保守性に長けたプログラムが可能になります。
MVCやMVPについて
ある程度オブジェクト指向を扱えるようになると、次はどれだけその設計が変更に対して柔軟であるかを考える必要が出てきます。
そんな時にMVCやMVPといった、設計パターンが有効的です。これを使う理由は多くのエンジニアに支持され使われる概念であり、これを適用することによって、複雑な設計に費やすコストや、拡張される際に犠牲にされるそのクラスの責任範囲や、処理の粒度といった問題を簡単に細分化させやすく、プログラミングの設計と保守が楽になります。しかしファイル数は増えるので実装量が実際には問題になってきます。ですがunitテストが書きやすいなどの利点が多く重宝されます。
UIスレッド
プログラムを動作させる単位にスレッドという仕組みがあります。このスレッドがあることで、バックグラウンドで動くアプリやシステムの動作があっても、アプリのプログラムを動作させることが可能になる仕組みです。(不要な説明かもしれませんが一応・・・)そして今まで説明したActivityやFragmentが動くスレッドをメインスレッドと呼びます。UIへの操作はここでしかできません。よって、メインスレッドをUIスレッドとも呼び、ここで重い(時間のかかる)処理をするとUIの表示が非常に重くなり、ANRでアプリが停止する原因になります。
またUIスレッドでは、通信を行うことができません。UIスレッドで通信を行うとアプリが停止します。つまりAndroidでは通信処理は意図的にUIスレッドに持ち込ませない仕組みを取り入れております。しかし他の処理ではそういう制御をシステム側でやってくれないので、UIスレッドでは数万件の情報を検索するDBアクセスや、大量のファイルへの読み書きなど重たい処理を行う場合は意図的に別のスレッドで操作させるようにしなくてはいけません。そういう場合はAndroidにはAsyncTaskという便利なユーティリティが存在するので是非活用するようにしてください。
ただしAsyncTaskは記述する場所やスレッドの生成や管理を意識しないで書くことができる程度で、非同期処理の問題はつきまとってきますので注意が必要です。
マルチスレッドプログラミング
現在の多くのアプリはユーザの操作だけではなく、サーバーやセンサーからもたらされる情報の更新通知を受け取ることで、アプリに必要なデータを配置します。
そのセンサーやサーバーから配信される内容を表示するためにUIを更新しようとしますが、ActivityやFragmentのライフサイクルイベントとは違い、不適切な状態でUIを更新をしようとすると、アプリが停止するなど、イベントドリブンでの複雑な処理は一筋縄ではいかないことが増えました。
そういったイベント処理の多くはスレッドの違うプログラムが同時に動作しており、それらの処理の順番を意識させないで実行させる非同期型の処理でデータが操作されるます。また自分で意図的に重い処理を別スレッドに分けたりもします。
そしてそういった、複数のスレッドを利用した非同期型の処理が複数あることをマルチスレッドプログラミングといいます。
近年Androidではこのマルチスレッドプログラミングが非常にアプリの動作の重要な役割をこなすようになってきました。
AndroidではUIスレッドできない処理をスレッド別に分担させることで、マルチスレッドプログラミングを行っていきます。
そしてAndroidで注意しなくてはいけないのはActivityやFragmentのライフサイクル状態を考慮してマルチスレッドプログラミングを実装させる必要があり、非常に困難な実装を求められることが多くなります。
マルチスレッドプログラミングを飼いならすことは非常に難しく、非常に良い経験になるはずです。
とりあえず以上になりますが、Intentや画面遷移などAndroidSDKの使い方はここでは割愛します。探せば見つかるものですからね。