シニアAndroid開発者の面接質問:Kotlin・Compose・アーキテクチャ

Milad Bonakdar
著者
Kotlinコルーチン、Jetpack Composeの状態管理、アーキテクチャ、パフォーマンス、テスト、オフラインファースト、セキュリティを実践的に確認できるシニアAndroid面接対策です。
はじめに
シニアAndroid開発者の面接では、アーキテクチャのトレードオフ、ライフサイクルに安全な並行処理、Composeの状態所有、オフラインファーストのデータフロー、パフォーマンス診断、テスト戦略、セキュリティを説明できる必要があります。強い回答は、使うAPIを答えるだけでなく、その選択がプロダクト上の制約に合う理由と、本番環境でどう調査するかまで示します。
このガイドは実践的なチェックリストとして使ってください。まずはKotlinコルーチンとFlow、ViewModelと状態管理、Roomを使ったリポジトリ、Composeと既存UIの判断、起動時間とメモリ、そして自分のアプリで説明できる具体例を優先しましょう。
使い方
- 各回答を「背景、トレードオフ、実装、失敗パターン」という短い判断として練習する。
- 技術選択を、起動の速さ、安定したオフライン読み取り、安全なトークン保存、ライフサイクル不具合の削減などのユーザー価値につなげる。
- アーキテクチャ、パフォーマンス、テスト、セキュリティについて、自分の実プロジェクトの話を1つずつ準備する。
高度な Kotlin と言語機能 (5つの質問)
1. Kotlin コルーチンとスレッドに対する利点を説明してください。
回答: コルーチンは、非同期コードを順次記述できる軽量な並行処理プリミティブです。
- スレッドに対する利点:
- 軽量: パフォーマンスの問題なく数千のコルーチンを作成できます
- 構造化された並行処理: 親子関係により、適切なクリーンアップが保証されます
- キャンセルサポート: キャンセルの伝播が組み込まれています
- 例外処理: 構造化された例外処理
- 主要コンポーネント:
- CoroutineScope: ライフサイクルを定義します
- Dispatchers: 実行コンテキストを制御します (Main, IO, Default)
- suspend 関数: 一時停止および再開できます
希少性: 非常に一般的 難易度: 難しい
2. シールドクラスとは何ですか?また、いつ使用すべきですか?
回答: シールドクラスは、すべてのサブクラスがコンパイル時に既知である制限されたクラス階層を表します。
- 利点:
- 網羅的な
when式 - 型安全な状態管理
- 複雑なデータには列挙型よりも優れています
- 網羅的な
- ユースケース: 状態、結果、ナビゲーションイベントの表現
希少性: 一般的 難易度: 普通
3. Kotlin Flow を説明し、LiveData との違いを説明してください。
回答: Flow は、値を順番に放出する Kotlin のコールド非同期ストリームです。
- Flow vs LiveData:
- Flow: コールドストリーム、演算子をサポート、ライフサイクルを認識しない、より柔軟
- LiveData: ホットストリーム、ライフサイクルを認識する、Android 固有、UI にはよりシンプル
- Flow の種類:
- Flow: コールドストリーム (収集時に開始)
- StateFlow: 現在の状態を持つホットストリーム
- SharedFlow: イベント用のホットストリーム
希少性: 非常に一般的 難易度: 難しい
4. インライン関数とは何ですか?また、いつ使用すべきですか?
回答: インライン関数は、関数呼び出しのオーバーヘッドを回避するために、関数本体を呼び出しサイトにコピーします。
- 利点:
- ラムダ割り当てのオーバーヘッドを排除
- ラムダからの非ローカルリターンを許可
- 高階関数でのパフォーマンス向上
- ユースケース: ラムダパラメータを持つ高階関数
- トレードオフ: コードサイズが増加します
希少性: 普通 難易度: 難しい
5. Kotlin の委譲について説明してください。
回答: 委譲により、オブジェクトはその責任の一部を別のオブジェクトに委譲できます。
- クラス委譲:
byキーワード - プロパティ委譲: Lazy、observable、delegates
- 利点: コードの再利用、継承よりもコンポジション
希少性: 普通 難易度: 普通
アーキテクチャパターン (6つの質問)
6. MVVM アーキテクチャとその利点を説明してください。
回答: MVVM (Model-View-ViewModel) は、UI ロジックをビジネスロジックから分離します。
- Model: データ層 (リポジトリ、データソース)
- View: UI 層 (Activity、Fragment、Composable)
- ViewModel: プレゼンテーションロジック、構成変更を乗り切る
- 利点: テスト可能、関心の分離、ライフサイクルを認識
希少性: 非常に一般的 難易度: 普通
7. クリーンアーキテクチャとは何ですか?また、Android でどのように実装しますか?
回答: クリーンアーキテクチャは、コードを明確な依存関係を持つレイヤーに分離します。
- Presentation: UI、ViewModels
- Domain: ユースケース、ビジネスロジック、エンティティ
- Data: リポジトリ、データソース (API、データベース)
- 依存性ルール: 内側のレイヤーは外側のレイヤーについて知りません
希少性: 一般的 難易度: 難しい
8. 依存性注入と Dagger/Hilt について説明してください。
回答: 依存性注入は、クラス内で依存関係を作成する代わりに、クラスに依存関係を提供します。
- 利点: テスト可能性、疎結合、再利用性
- Dagger: コンパイル時の DI フレームワーク
- Hilt: Android 向けの簡略化された Dagger
希少性: 非常に一般的 難易度: 難しい
9. リポジトリパターンとは何ですか?また、なぜ使用するのですか?
回答: リポジトリパターンはデータソースを抽象化し、データアクセス用のクリーンな API を提供します。
- 利点:
- 信頼できる唯一の情報源
- 集中化されたデータロジック
- データソースの切り替えが簡単
- テスト可能
- 実装: 複数のデータソース間の調整
希少性: 非常に一般的 難易度: 普通
10. シングルアクティビティアーキテクチャについて説明してください。
回答: シングルアクティビティアーキテクチャは、ナビゲーションコンポーネントによって管理される複数のフラグメントを持つ 1 つのアクティビティを使用します。
- 利点:
- 簡略化されたナビゲーション
- フラグメント間の共有 ViewModel
- より優れたアニメーション
- より簡単なディープリンク
- ナビゲーションコンポーネント: フラグメントトランザクション、バックスタック、引数を処理します
希少性: 一般的 難易度: 普通
11. MVI (Model-View-Intent) アーキテクチャとは何ですか?
回答: MVI は、Redux に触発された単方向データフローアーキテクチャです。
- コンポーネント:
- Model: UI 状態を表します
- View: 状態をレンダリングし、インテントを放出します
- Intent: ユーザーアクション/イベント
- 利点: 予測可能な状態、簡単なデバッグ、タイムトラベルデバッグ
希少性: 普通 難易度: 難しい
パフォーマンスと最適化 (5つの質問)
12. RecyclerView のパフォーマンスを最適化するにはどうすればよいですか?
回答: 複数の戦略により、RecyclerView のスクロールパフォーマンスが向上します。
- ViewHolder パターン: ビューを再利用します (組み込み)
- DiffUtil: 効率的なリスト更新
- 安定した ID:
getItemId()をオーバーライドし、setHasStableIds(true)を設定します - プリフェッチ: プリフェッチ距離を増やします
- 画像の読み込み: Glide/Coil などのライブラリを適切なサイズで使用します
- 重い操作の回避:
onBindViewHolderでコストのかかる計算を実行しないでください - ネストされた RecyclerView:
setRecycledViewPool()とsetHasFixedSize(true)を設定します
希少性: 非常に一般的 難易度: 普通
13. Android でメモリリークを検出して修正するにはどうすればよいですか?
回答: メモリリークは、オブジェクトが必要以上に長くメモリに保持されている場合に発生します。
- 一般的な原因:
- コンテキストリーク (Activity/Fragment 参照)
- 静的参照
- 匿名内部クラス
- 登録解除されていないリスナー
- キャンセルされていないコルーチン
- 検出ツール:
- LeakCanary ライブラリ
- Android Studio Memory Profiler
- ヒープダンプ
希少性: 非常に一般的 難易度: 普通
14. アプリの起動時間を最適化するにはどうすればよいですか?
回答: 起動時間の短縮はユーザーエクスペリエンスを向上させます。
- 遅延初期化: オブジェクトが必要な場合にのみ初期化します
- Application.onCreate() での重い処理の回避:
- バックグラウンドスレッドに移動
- 重要でない初期化を延期
- コンテンツプロバイダー: 最小化または遅延読み込み
- 依存関係の削減: ライブラリが少ないほど、起動が速くなります
- App Startup Library: 構造化された初期化
- Baseline Profiles: 事前コンパイルのヒント
希少性: 一般的 難易度: 普通
15. ビットマップの読み込みとキャッシュを効率的に処理するにはどうすればよいですか?
回答: 効率的な画像処理は、パフォーマンスにとって非常に重要です。
- ライブラリ: Glide、Coil (自動的にキャッシュを処理)
- 手動最適化:
- ダウンサンプリング (より小さな画像を読み込む)
- メモリキャッシュ (LruCache)
- ディスクキャッシュ
- ビットマッププーリング
希少性: 一般的 難易度: 難しい
16. ANR とは何ですか?また、どのように防止しますか?
回答: ANR (Application Not Responding) は、メインスレッドが長時間ブロックされている場合に発生します。
- 原因:
- メインスレッドでの重い計算
- メインスレッドでのネットワーク呼び出し
- メインスレッドでのデータベース操作
- デッドロック
- 防止:
- 重い処理をバックグラウンドスレッドに移動
- 適切なディスパッチャを持つコルーチンを使用
- メインスレッドでの synchronized ブロックの回避
- バックグラウンドタスクに WorkManager を使用
希少性: 一般的 難易度: 簡単
テスト (3つの質問)
17. ViewModels の単体テストはどのように記述しますか?
回答: ViewModels は、


