android-development について
Google の公式アーキテクチャ指針と NowInAndroid の実装例に基づく、Android 開発向けスキルです。新規プロジェクトや機能追加に向けて、モジュール構成、Compose UI、データ層、Gradle 設定、テストのパターンを示します。
主な機能
- 01機能単位のモジュール構成
- 02UI・Domain・Data のレイヤー
- 03Jetpack Compose のパターン
- 04Gradle とビルド設定のガイド
- 05テストとオフライン優先設計
活用シーン
- 01参考パターンに沿った Android プロジェクト作成
- 02機能の API・実装モジュールを用意
- 03Compose 画面と ViewModel の実装
- 04データ層とテスト方法の設定
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ dpconde/ claude-android-skill --skill android-developmentインストール後、Claude Code で/android-developmentを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
.gitignoreLICENSEREADME.mdassets/templates/settings.gradle.kts.templatelibs.versions.toml.templatereferences/compose-patterns.mdarchitecture.mdmodularization.mdgradle-setup.mdtesting.mdscripts/generate_feature.py詳細
Android 開発
NowInAndroid リファレンスアプリで実証されている、Google の公式アーキテクチャガイダンスに従って Android アプリケーションを構築します。
クイックリファレンス
| タスク | 参照ファイル |
|---|---|
| プロジェクト構造とモジュール | modularization.md |
| アーキテクチャレイヤー(UI、Domain、Data) | architecture.md |
| Jetpack Compose のパターン | compose-patterns.md |
| Gradle とビルド設定 | gradle-setup.md |
| テストのアプローチ | testing.md |
ワークフローの判断ツリー
新しいプロジェクトを作成しますか?
→ modularization.md を読んで、プロジェクト構造を確認します
→ assets/templates/ のテンプレートを使用します
新しい機能を追加しますか?
→ api と impl のサブモジュールを持つ機能モジュールを作成します
→ architecture.md のパターンに従います
UI 画面を構築しますか? → compose-patterns.md を読みます → Screen + ViewModel + UiState を作成します
データレイヤーを設定しますか? → architecture.md のデータレイヤーのセクションを読みます → Repository + DataSource + DAO を作成します
基本原則
- オフラインファースト:ローカルデータベースを信頼できる情報源とし、リモートと同期します
- 単方向データフロー:イベントは下方向に流れ、データは上方向に流れます
- リアクティブストリーム:すべてのデータ公開に Kotlin Flow を使用します
- 機能ごとのモジュール化:各機能は明確な境界を持つ自己完結型です
- 設計段階からテスト可能:インターフェースとテスト用代替実装を使用し、モックライブラリは使いません
アーキテクチャレイヤー
┌─────────────────────────────────────────┐
│ UI Layer │
│ (Compose Screens + ViewModels) │
├─────────────────────────────────────────┤
│ Domain Layer │
│ (Use Cases - optional, for reuse) │
├─────────────────────────────────────────┤
│ Data Layer │
│ (Repositories + DataSources) │
└─────────────────────────────────────────┘
モジュールの種類
app/ # App module - navigation, scaffolding
feature/
├── featurename/
│ ├── api/ # Navigation keys (public)
│ └── impl/ # Screen, ViewModel, DI (internal)
core/
├── data/ # Repositories
├── database/ # Room DAOs, entities
├── network/ # Retrofit, API models
├── model/ # Domain models (pure Kotlin)
├── common/ # Shared utilities
├── ui/ # Reusable Compose components
├── designsystem/ # Theme, icons, base components
├── datastore/ # Preferences storage
└── testing/ # Test utilities
新しい機能の作成
- ナビゲーションキーを含む
feature:myfeature:apiモジュールを作成します - 次の要素を含む
feature:myfeature:implモジュールを作成します:MyFeatureScreen.kt- コンポーザブル UIMyFeatureViewModel.kt- 状態ホルダーMyFeatureUiState.kt- 状態を表すシールドインターフェースMyFeatureNavigation.kt- ナビゲーション設定MyFeatureModule.kt- Hilt DI モジュール
標準的なファイルパターン
ViewModel パターン
@HiltViewModel
class MyFeatureViewModel @Inject constructor(
private val myRepository: MyRepository,
) : ViewModel() {
val uiState: StateFlow<MyFeatureUiState> = myRepository
.getData()
.map { data -> MyFeatureUiState.Success(data) }
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = MyFeatureUiState.Loading,
)
fun onAction(action: MyFeatureAction) {
when (action) {
is MyFeatureAction.ItemClicked -> handleItemClick(action.id)
}
}
}
UiState パターン
sealed interface MyFeatureUiState {
data object Loading : MyFeatureUiState
data class Success(val items: List<Item>) : MyFeatureUiState
data class Error(val message: String) : MyFeatureUiState
}
Screen パターン
@Composable
internal fun MyFeatureRoute(
onNavigateToDetail: (String) -> Unit,
viewModel: MyFeatureViewModel = hiltViewModel(),
) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
MyFeatureScreen(
uiState = uiState,
onAction = viewModel::onAction,
onNavigateToDetail = onNavigateToDetail,
)
}
@Composable
internal fun MyFeatureScreen(
uiState: MyFeatureUiState,
onAction: (MyFeatureAction) -> Unit,
onNavigateToDetail: (String) -> Unit,
) {
when (uiState) {
is MyFeatureUiState.Loading -> LoadingIndicator()
is MyFeatureUiState.Success -> ContentList(uiState.items, onAction)
is MyFeatureUiState.Error -> ErrorMessage(uiState.message)
}
}
Repository パターン
interface MyRepository {
fun getData(): Flow<List<MyModel>>
suspend fun updateItem(id: String, data: MyModel)
}
internal class OfflineFirstMyRepository @Inject constructor(
private val localDataSource: MyDao,
private val networkDataSource: MyNetworkApi,
) : MyRepository {
override fun getData(): Flow<List<MyModel>> =
localDataSource.getAll().map { entities ->
entities.map { it.toModel() }
}
override suspend fun updateItem(id: String, data: MyModel) {
localDataSource.upsert(data.toEntity())
}
}
主な依存関係
// Gradle version catalog (libs.versions.toml)
[versions]
kotlin = "1.9.x"
compose-bom = "2024.x.x"
hilt = "2.48"
room = "2.6.x"
coroutines = "1.7.x"
[libraries]
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
ビルド設定
一貫性のある設定のため、build-logic/ のコンベンションプラグインを使用します:
AndroidApplicationConventionPlugin- アプリモジュールAndroidLibraryConventionPlugin- ライブラリモジュールAndroidFeatureConventionPlugin- 機能モジュールAndroidComposeConventionPlugin- Compose の設定AndroidHiltConventionPlugin- Hilt の設定
ビルド設定の全容については、gradle-setup.md を参照してください。
コメント
Markdown 対応