Slide 1

Slide 1 text

Android™研修 2022ver 2022/04/26 Android は Google LLC の商標です。

Slide 2

Slide 2 text

講師・チューター紹介 ● 講師 ○ 山田 淳登 (slack: atsuto.yamada) ○ 2015新卒 ○ TIPSTAR Android版 開発リーダー ● チューター ○ 太田 祐樹 (slack: yuki.ota) ○ 2021.09入社 2014高専卒 ○ Androidは2018年頃からやっています

Slide 3

Slide 3 text

研修の目的と範囲 ● 目的 ○ 基礎的な部分の学習 ○ Android開発の特徴・魅力が分かる ● 範囲 ○ Androidの実行環境の概要 ○ UIレイアウト ○ リスト(RecyclerView) ○ 非同期処理とKotlin Coroutine ○ リアクティブストリーム( LiveData) ○ MotionLayout ○ ハンズオン(ストップウォッチを作ってみよう) ■ 一緒にやるハンズオンと、自分で手を動かしてもらうハンズオンがある ※Kotlin文法は範囲外 10:31

Slide 4

Slide 4 text

はじめに この研修の最終目標 ラップ機能付きストップウォッチを作る 10:32

Slide 5

Slide 5 text

Androidアプリの基本構造① 10:32

Slide 6

Slide 6 text

Androidネイティブアプリとは ● Androidランタイム(ART)上で動くアプリ ○ Java Virtual Machineではない ○ Java APIが利用できる ○ ただし独自実装のため、 Javaとは動作が異なるAPIも存在する ● 開発言語は主にJava or Kotlin ○ 今ではKotlinが主流 ○ バイトコード(class)を吐き出すことができれば良い ■ 例えばScalaでも開発可能 10:32

Slide 7

Slide 7 text

JavaとKotlinの関係 ● Java, Kotlin どちらもバイトコードを生成するための手段 ● Kotlinでしか利用できない独自APIがある ○ これが開発者がKotlinを選ぶ最大の理由 Java Kotlin バイトコード .class 実行可能形式 .dex パッケージ .apk ︙ 10:33

Slide 8

Slide 8 text

開発環境 ● Android Studioと呼ばれるIDEを利用 ○ IntelliJ IDEAベース 10:33

Slide 9

Slide 9 text

ディレクトリ構成 ● 初期状態では実際のディレクトリ構成で表示され ない ● 左側のディレクトリツリーでProjectに切り替える と実際のディレクトリ構成になる ● こちらの方が分かりやすいのでオススメ 10:34

Slide 10

Slide 10 text

ディレクトリ構成 ● app/src/main/res ○ リソースを入れる場所 ■ 画像、図形、UIレイアウト、テキスト など ● app/src/main/java ○ Java, Kotlinのコードを入れる場所 ● app/build.gradle ○ アプリのビルド時に必要な情報を記すファイル ■ SDKバージョン ■ 外部ライブラリ ● app/src/main/AndroidManifest.xml ○ アプリの構成情報を記すファイル 10:34

Slide 11

Slide 11 text

リソースディレクトリ ● app/src/main/res ○ values/strings.xml ■ アプリ内のUIで表示する文字列を定義する ■ Java, Kotlinコード上に表示文字列を書くことはほぼ無い ● 実行環境の言語設定によって内容を変えるため ○ values/colors.xml ■ アプリで利用する色コードを定義する ○ values/themes.xml ■ UIパーツの見た目の変更を定義する 10:35

Slide 12

Slide 12 text

app/build.gradle ● ビルド時に必要な情報が定義されている ● アプリのバージョン ● compileSdk ○ どのAndroid SDKバージョンでビルドするか ○ 32 = Android 12 ● minSdk ○ 動作可能な最低のAndroidバージョン ● パッケージ名(applicationId) ○ アプリを特定するための ID ● 外部依存ライブラリ(dependencies) 10:35

Slide 13

Slide 13 text

AndroidManifest.xml ● アプリの構成情報 ● アプリにどんな画面があるのか(Activity) ● アプリにどんなサービスがあるのか(Service) ○ サービスとは? ■ 画面を持たないバックグラウンド処理を行うもの ■ 消費電力節約の観点から、近年多用はされない ■ プッシュ通知で使われる ● アプリ名 ● アプリアイコン ● 外部アプリから自分のアプリ画面への呼び出し方法の定義(IntentFilter) ○ 例:別アプリで「共有」を押すと、データを受け取りつつ自分のアプリを開く 10:36

Slide 14

Slide 14 text

Androidアプリの基本構造② 10:36

Slide 15

Slide 15 text

Activity ● Androidでは1枚の画面をActivityという機能を利用して実装する ○ AppCompatActivity:Androidバージョン間の互換性を維持するためのクラス ● 画面内で行う処理は、Activityを起点に処理が伸びていく ● 画面ごとにAppCompatActivityを継承したクラスを作成する 10:37

Slide 16

Slide 16 text

Activityのライフサイクル ● ライフサイクルとは ○ 画面のステートによって呼ばれるメソッドと、その順序 ● 画面のステート ○ ステートの例:画面を開く、画面を起動したまま別アプリを開く、画 面を閉じる ● onCreateで画面の初期化を行う ● onDestroyで画面の終了処理を行う 画面の起動 onCreate onStart onResume 画面の表示 onPause onStop onDestroy 画面の終了 画面が見えな くなる 10:37

Slide 17

Slide 17 text

ハンズオン①:サンプルプロジェクトの起動 ● サンプルプロジェクトを起動してみる ● プロジェクトをCloneする。以下をターミナルで実行 cd ~ mkdir AndroidStudioProjects cd AndroidStudioProjects git clone [email protected]:mixigroup/AndroidTraining2022.git cd AndroidTraining2022 git checkout lesson1 10:50

Slide 18

Slide 18 text

ハンズオン①:サンプルプロジェクトの起動 ● AndroidStudioを起動 ● Openをクリック 10:50

Slide 19

Slide 19 text

ハンズオン①:サンプルプロジェクトの起動 ● 先程Cloneしたディレクトリを選択し、Openをクリック ● 「Trust Gradle Project?」と出たら、Trust Projectをクリック 10:50

Slide 20

Slide 20 text

ハンズオン①:サンプルプロジェクトの起動 ● アプリをエミュレーター上で実行する 10:50

Slide 21

Slide 21 text

11:15まで休憩時間 11:15

Slide 22

Slide 22 text

UIレイアウト 11:15

Slide 23

Slide 23 text

View ● Viewとは:画面上に何かを表示するためのコンポーネント ● Viewを継承したさまざまなクラスがSDKで用意されている ● 代表的なView ○ TextView:文字列を表示 ○ ImageView:画像を表示 ○ Button:ボタンを表示 ○ EditText:文字列入力フォームを表示 ● 画面で必要なViewをXMLで記述する(レイアウトXML) 11:16

Slide 24

Slide 24 text

レイアウトXMLとActivity(Kotlinコード)の関係 ● Viewを利用するにはインスタンスが必要 ● レイアウトXMLをViewインスタンスに変換することでプログラム上で利用可能となる ● レイアウトXMLはViewインスタンスを用意するための手段 ○ レイアウトに限らず、 AndroidでのXML定義要素はすべてインスタンス化して利用する ● レイアウトXMLをインスタンス化する機能はLayoutInflaterが提供 ● 1つのXMLに存在するViewをまとめるためのHolderとしてViewBindingが利用され る ● ActivityにsetContentViewすることで、その画面のUIとして利用される XML View View View View View ViewBinding 11:17

Slide 25

Slide 25 text

TextView ● 文字列を表示するためのView ● XML属性を変更することで書式の変更が可能 ○ android:id Viewを特定するためのID ○ style 別途定義した属性を引っ張ってくる ○ android:text 表示するテキスト内容 ○ android:textColor テキスト色 ○ android:textSize テキストサイズ ● リソースとして定義した値は @.../ で参照 ○ @color/ ○ @string/ 11:18

Slide 26

Slide 26 text

Button ● ボタンを表示するためのView ● TextViewのサブクラスなので、TextViewの属性と共通 11:18

Slide 27

Slide 27 text

サイズ単位 sp, dp ● 世の中のAndroid端末のディスプレイは、高解像度・低解像度が混在している ● よって、pixel単位をそのまま利用できない ○ 低解像度ディスプレイでは大きく、高解像度ディスプレイでは小さく表示される ● サイズ指定は dp を使う ○ 画面のピクセル密度を考慮したサイズ指定が可能 ● テキストサイズ指定では sp を使う ○ 画面のピクセル密度に加え、 OSのフォントサイズ設定によって変化する単位 ○ フォントサイズ標準時、 14sp = 14dp 11:19

Slide 28

Slide 28 text

ViewGroupとは ● ViewGroupとは:Viewを複数並べるためのコンポーネント ● 代表的なViewGroup ○ FrameLayout:重ねて表示 ○ LinearLayout:縦方向や横方向に並べて表示 ○ ConstraintLayout:View同士の制約(並べ方)を定義して表示 ○ ScrollView:表示領域をはみ出るくらいの大きな Viewをスクロール可能にする ○ RecyclerView:スクロール可能な表示領域のみ Viewを配置する ● これも同じくレイアウトXMLに記述する 11:20

Slide 29

Slide 29 text

LinearLayout ● 縦方向や横方向に並べて表示する ● android:orientation ○ vertical 縦に並べる ○ horizontal 横に並べる 11:21

Slide 30

Slide 30 text

ConstraintLayout ● View同士の制約を設定して並べる start(左側面)を親の左側面にくっつける top(上側面)を親の上側面にくっつける start(左側面)をTEXT_1の右側面にくっつける top(上側面)をTEXT_1の下側面にくっつける 11:21

Slide 31

Slide 31 text

ViewGroupに対しての属性指定 ● ViewGroupに属しているViewは、親に対してどのよ うなサイズ・位置にするかを指定できる ○ layout_…がついている属性は親に対する指定 ● android:layout_width, android:layout_height ○ wrap_content Viewのコンテンツが収まるように ○ match_parent 親要素の大きさに合わせる ● android:layout_margin… ○ マージンを取って位置を決定する 11:22

Slide 32

Slide 32 text

ConstraintLayout Chain ● ConstraintLayoutにおいて、お互いに依存し合った制約が設定されている場 合、うまくセンタリングされる ● その際の並べ方を指定できる ● android:layout_constraint(Horizontal/Vertical)_chainStyle ○ packed ○ spread ○ spread_inside packed spread spread_inside 11:23

Slide 33

Slide 33 text

ConstraintLayout Chainの作り方(エディタ上) ● (実際に解説 ブランチ名:example1) ● Designを開きComponent Treeから複数のViewを選び、右クリックで作成 11:30

Slide 34

Slide 34 text

ハンズオン②:【課題】秒数表示・ボタンを置く ● ブランチ lesson2 をcheckout ● 課題 ○ MainActivityに紐付いているactivity_main.xmlを編集 ○ 右のようにTextViewとButtonを配置する ○ (必要なパラメーターは次ページ) ● 時間:10分間(11:47まで) 11:47

Slide 35

Slide 35 text

ハンズオン②:【課題】秒数表示・ボタンを置く マージン36dp マージン36dp 均等 均等 11:45

Slide 36

Slide 36 text

ハンズオン②:正解解説 ● (実際に解説 ブランチ名:lesson2-answer) 11:45

Slide 37

Slide 37 text

ActivityからViewを操作する 12:00

Slide 38

Slide 38 text

ActivityにViewを設定する ● XMLで定義したViewは binding に格納され ている ● activity_main.xml → ActivityMainBinding ● setContentViewでActivityの画面として設 定する 12:01

Slide 39

Slide 39 text

ActivityからViewを操作する ● id: time_text → timeText ● binding内にインスタンスがあるので、その プロパティをコード側で変更できる 12:02

Slide 40

Slide 40 text

任意のタイミングでViewを操作する ● setOnClickListenerを使うことで、Viewが クリックされた時に動作させることができ る 12:03

Slide 41

Slide 41 text

リストの表示 12:03

Slide 42

Slide 42 text

なぜRecyclerViewを使うのか ● リスト表示ではRecyclerViewの利用が必須 ● LinearLayoutを使ってリストを作成するとアイテ ムが多数あった場合、描画する必要の無い領 域までViewがレイアウトされる ○ リストの要素が100個あればTextViewが100個必要に なる ○ 見えている領域は十数個だけ。十数個しか使わないの に無駄 ︙ 画面領域が赤線部分だとすると この領域外のTextViewが無駄 12:04

Slide 43

Slide 43 text

なぜRecyclerViewを使うのか ● RecyclerViewを使うと、表示領域分だけViewを レイアウトできる ● スクロールすると必要に応じてViewが新規作成・ 再利用される 12:05

Slide 44

Slide 44 text

なぜRecyclerViewを使うのか ● スクロールすると、領域外に出たViewがリサイク ルされる ● リサイクルされたViewは次に見えるアイテムとし てレイアウトされる 12:05

Slide 45

Slide 45 text

RecyclerViewを使う ● リスト内の1アイテム分のレイアウトXMLを新規作成する ● 表示箇所にRecyclerViewを配置 ● app:layoutManager ○ 並べ方を設定 ○ androidx.recyclerview.widget.LinearLayoutManager ■ LinearLayoutのように縦方向に並べる 12:06

Slide 46

Slide 46 text

RecyclerViewを使う ● RecyclerView.Adapterを実装する ○ リストにあるデータをViewに変換する ● ハンズオンではこの実装である ListAdapter を 利用 ● onCreateViewHolder ○ ViewHolderを返す ■ アイテム内で使うViewを保持するクラス ■ 歴史的にはViewBindingが後発 ● onBindViewHolder ○ positionに位置するデータを Viewに設定する 12:06

Slide 47

Slide 47 text

ハンズオン③:リスト表示する ● 一緒にやるハンズオン ● ブランチ lesson3 をcheckout ● 解説 ○ ボタンを押すとリストにアイテムが追加される実装 ○ Adapterの実装 ○ MainActivity側の実装 12:15

Slide 48

Slide 48 text

昼休憩:13:30まで 13:30

Slide 49

Slide 49 text

非同期処理 13:30

Slide 50

Slide 50 text

Androidにおける非同期処理 ● Androidにおける処理スレッドの種類 ○ Mainスレッド(UIスレッド) ○ IOスレッド(バックグラウンドスレッド) ● onCreateなどのフレームワークからのコールバックはMainスレッドで呼ばれる ● Mainスレッドで重い処理やネットワーク通信を行うと ○ 処理(通信)が終わるまでアプリが固まる ○ ネットワーク通信はフレームワークの制約によりそもそもできない(クラッシュする) ● Viewの操作はMainスレッドで行う必要がある ○ IOスレッド→Mainスレッドへのコールバックが必要 13:30

Slide 51

Slide 51 text

Kotlin Corouines ● 同一ブロック内で中断可能なスコープ ○ →CoroutineScope ○ Activityに連動したCorouineScopeは lifecycleScope.launch で生成 ● 通常 Thread.sleep を使うとスレッドが停止す る ● delay を使うとスレッドが停止せず、別ブロック にある処理を続行する ● 実行スレッドを同一ブロック内で変更可能

Slide 52

Slide 52 text

Kotlin Corouines ● 処理が不要になったら適切にCoroutineScopeが終了される ○ アプリが終了すれば停止する ● while無限ループもガシガシ使える 13:33

Slide 53

Slide 53 text

Kotlin Corouines ● withContextを利用することで、そのブロックだけ別のスレッドで実行が可能 ● (無駄ではあるが)インクリメントだけIOスレッドで実行している ○ Dispatcher.MainでMainスレッドでの実行も指定できる。 13:35

Slide 54

Slide 54 text

ViewModelとLiveData 13:36

Slide 55

Slide 55 text

責務の分離 ● 画面に機能を実装していくとActivityの肥大化する ○ 可読性の低下 ○ メンテナンスコストの増加 ○ バグの増加 ● 各クラスが特定の処理に集中できる設計が重要 ○ →ViewModelの登場 13:37 Activity ViewModel ViewModelが用意した データをViewに設定す ることに集中 UI表示するデータを用意 することに集中 データ

Slide 56

Slide 56 text

ViewModel ● AndroidViewModel を継承したクラスを用意 ● by viewModels() ○ Activity内でのViewModel生成 13:38

Slide 57

Slide 57 text

LiveData ● ViewModelがActivityに依存することは許されない ○ インスタンスの生存期間が異なる・責務分離の明確化 などの理由 ● ViewModelからActivityにデータを伝える方法が必要 ○ →LiveDataを使う ● LiveData:データの入れ物 ● 更新を通知する機能が備わっている ● LiveData.observe ○ データの変化時に実行されるリスナーを設定する 13:39

Slide 58

Slide 58 text

LiveDataの仲間たち ● MutableLiveData ○ 外部から自由に変更可能な LiveData ○ setValue(Kotlin上からは value と省略)でデータを設定 ● MediatorLiveData ○ 別のLiveData(ソース)を元にデータ設定できる LiveData ○ addSource ■ 別のLiveDataソースを設定 ■ ソースの値変更されたら、ブロックが呼ばれる 13:40

Slide 59

Slide 59 text

MediatorLiveDataのショートカットたち ● LiveData.map { } ○ 他のLiveDataの値を変換する 13:41

Slide 60

Slide 60 text

MediatorLiveDataのショートカットたち ● LiveData.switchMap { } ○ 他のLiveDataの値が変化したら、参照する LiveDataを切り替える ○ ※liveData { } ブロックは次に紹介 13:42

Slide 61

Slide 61 text

Coroutine LiveData(liveData{ }) ● ActivityがObserveしている間だけ動 作するCoroutineScopeを生成 ● ブロック内でデータを生成し、emit() することで値を更新する 13:45

Slide 62

Slide 62 text

ハンズオン④:LiveDataでステートを管理する ● 一緒にやるハンズオン ● ブランチ lesson4 をcheckout ● ViewModelにあるLiveDataでストップウォッチのステート を管理する ● ステートを元に右側のボタンの以下を変更 ○ テキスト ○ 色 ○ クリックアクション 14:05

Slide 63

Slide 63 text

ハンズオン⑤:ストップウォッチの秒数を表示する ● ブランチ lesson5 をcheckout ● 課題 ○ MainViewModel.currentTimeを元に、currentTimeTextの中身を 実装 ○ currentTimeTextをTextViewに表示 ● 時間:20分間(14:33まで) 14:33

Slide 64

Slide 64 text

ハンズオン⑤:ストップウォッチの秒数を表示する ● (解説 ブランチ名:lesson5-answer) 14:35

Slide 65

Slide 65 text

14:50まで(10分)休憩

Slide 66

Slide 66 text

MotionLayout 14:50

Slide 67

Slide 67 text

MotionLayout ● Viewを移動させるコンポーネント(ViewGroup) ● ConstraintLayoutのサブクラス ● 開始状態と終了状態の制約を定義、その間をアニメーションさせる ○ レイアウトXMLとは別に、MotionSceneというXMLを用意する 14:50

Slide 68

Slide 68 text

MotionLayout TextView(time_text)を移動させる例 親要素 ConstraintLayoutをMotionLayoutに変更 app:layoutDescriptionを追加 MotionSceneが定義されたxmlを指定 動かしたいViewの制約を削除 14:51

Slide 69

Slide 69 text

MotionLayout Transitionに開始・終了ステートと、遷移時間 を設定 Constraintで開始ステートにおける制約を設 定 Constraintに終了ステートにおける制約を設 定 14:52

Slide 70

Slide 70 text

MotionLayout ● transitionToEnd() ○ 終了ステートに遷移 ● transitionToStart() ○ 開始ステートに遷移 14:53

Slide 71

Slide 71 text

ハンズオン⑥:MotionLayoutを使ってViewを移動させる ● 一緒にやるハンズオン ● ブランチ lesson6 をcheckout ● ラップボタンを押すと、time_text を上に上げ つつ、recycler_view_header, recycler_view が見えるようにする 15:10

Slide 72

Slide 72 text

ハンズオン⑦:最終課題 ● ブランチ lesson7 をcheckout ● 1時間(16:15まで) ● ラップ機能を完成させる ○ ストップウォッチ開始中だけ、ラップボタンを有効にする (Button.isEnabled) ○ ラップ時間表示を実装する ○ ラップがあるときは時間表示を上げる ○ ラップがないときは時間表示を下げる ● 完成したら、別ブランチで差分をpushし、lesson7 へのPRを作成 16:10