jpskill.com
🛠️ 開発・MCP コミュニティ

android-patterns

KotlinでのAndroidアプリ開発における、コルーチンやライフサイクル管理、関数型プログラミングといった主要なパターンを効率的に活用し、より高品質なアプリ開発を支援するSkill。

📜 元の英語説明(参考)

Core Android development patterns for Kotlin, including coroutines, lifecycle management, and functional programming idioms.

🇯🇵 日本人クリエイター向け解説

一言でいうと

KotlinでのAndroidアプリ開発における、コルーチンやライフサイクル管理、関数型プログラミングといった主要なパターンを効率的に活用し、より高品質なアプリ開発を支援するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o android-patterns.zip https://jpskill.com/download/16401.zip && unzip -o android-patterns.zip && rm android-patterns.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/16401.zip -OutFile "$d\android-patterns.zip"; Expand-Archive "$d\android-patterns.zip" -DestinationPath $d -Force; ri "$d\android-patterns.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して android-patterns.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → android-patterns フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

Android開発パターン

Kotlin、コルーチン、および関数型プログラミングを用いた現代的なAndroidのパターンです。

Kotlinのイディオム

不変性

// ✅ varよりもvalを優先する
val name: String = "John"

// ✅ 不変コレクション
val items: List<Item> = listOf(item1, item2)

// ✅ copyを持つデータクラス
data class User(val id: String, val name: String)
val updatedUser = user.copy(name = "Jane")

Null安全性

// ✅ セーフコール
val length = name?.length

// ✅ Elvis演算子
val name = nullableName ?: "Unknown"

// ✅ nullチェックのためのlet
nullableUser?.let { user ->
    processUser(user)
}

// ✅ nullチェックによる早期リターン
fun processUser(user: User?) {
    user ?: return
    // userはnon-nullにスマートキャストされる
}

スコープ関数

// let - 変換して返す
val result = nullable?.let { transform(it) }

// run - 設定して結果を返す
val result = service.run {
    configure()
    execute()
}

// with - オブジェクトを操作する
with(binding) {
    title.text = "Title"
    subtitle.text = "Subtitle"
}

// apply - 設定して自身を返す
val user = User().apply {
    name = "John"
    email = "john@example.com"
}

// also - 副作用、自身を返す
val user = User().also {
    logger.log("Created user: ${it.id}")
}

拡張

// ✅ 拡張関数
fun String.isValidEmail(): Boolean {
    return android.util.Patterns.EMAIL_ADDRESS.matcher(this).matches()
}

// ✅ 拡張プロパティ
val Context.screenWidth: Int
    get() = resources.displayMetrics.widthPixels

// 使用例
if (email.isValidEmail()) { ... }
val width = context.screenWidth

ライフサイクルパターン

ViewModel

class HomeViewModel(
    private val repository: HomeRepository,
    savedStateHandle: SavedStateHandle
) : ViewModel() {

    private val _state = MutableStateFlow(HomeState())
    val state: StateFlow<HomeState> = _state.asStateFlow()

    init {
        loadData()
    }

    private fun loadData() {
        viewModelScope.launch {
            _state.update { it.copy(isLoading = true) }

            repository.getItems()
                .onSuccess { items -> _state.update { it.copy(items = items, isLoading = false) } }
                .onFailure { error -> _state.update { it.copy(error = error.message, isLoading = false) } }
        }
    }
}

ライフサイクルを意識したコレクション

@Composable
fun HomeScreen(viewModel: HomeViewModel = koinViewModel()) {
    val state by viewModel.state.collectAsStateWithLifecycle()

    HomeContent(state = state)
}

関数型パターン

Result型

// ✅ 失敗する可能性のある操作にはResultを使用する
suspend fun fetchUser(id: String): Result<User> = runCatching {
    api.getUser(id).toDomain()
}

// ✅ 操作をチェーンする
repository.fetchUser(id)
    .map { it.profile }
    .mapCatching { decryptProfile(it) }
    .onSuccess { displayProfile(it) }
    .onFailure { showError(it) }

高階関数

// ✅ 関数をパラメータとして渡す
fun <T> retry(
    times: Int,
    block: suspend () -> T
): T {
    repeat(times - 1) {
        try { return block() }
        catch (e: Exception) { delay(1000) }
    }
    return block() // 最後の試行
}

// 使用例
val result = retry(3) { api.fetchData() }

Sealed Classes

sealed interface UiState<out T> {
    data object Loading : UiState<Nothing>
    data class Success<T>(val data: T) : UiState<T>
    data class Error(val message: String) : UiState<Nothing>
}

// Exhaustive when
when (state) {
    is UiState.Loading -> LoadingIndicator()
    is UiState.Success -> Content(state.data)
    is UiState.Error -> ErrorMessage(state.message)
}

リソース管理

Contextの拡張

fun Context.dp(value: Int): Int = 
    (value * resources.displayMetrics.density).toInt()

fun Context.showToast(message: String) {
    Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}

文字列リソース

// strings.xml
<string name="welcome_message">Welcome, %1$s!</string>

// 使用例
stringResource(R.string.welcome_message, userName)

覚えておいてください: Kotlinは簡潔です。よりクリーンで安全なコードのために、そのイディオムを取り入れましょう。

📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Android Development Patterns

Modern Android patterns with Kotlin, coroutines, and functional programming.

Kotlin Idioms

Immutability

// ✅ Prefer val over var
val name: String = "John"

// ✅ Immutable collections
val items: List<Item> = listOf(item1, item2)

// ✅ Data class with copy
data class User(val id: String, val name: String)
val updatedUser = user.copy(name = "Jane")

Null Safety

// ✅ Safe call
val length = name?.length

// ✅ Elvis operator
val name = nullableName ?: "Unknown"

// ✅ let for null checks
nullableUser?.let { user ->
    processUser(user)
}

// ✅ Early return with null check
fun processUser(user: User?) {
    user ?: return
    // user is smart-cast to non-null
}

Scope Functions

// let - Transform and return
val result = nullable?.let { transform(it) }

// run - Configure and return result
val result = service.run {
    configure()
    execute()
}

// with - Operate on object
with(binding) {
    title.text = "Title"
    subtitle.text = "Subtitle"
}

// apply - Configure and return self
val user = User().apply {
    name = "John"
    email = "john@example.com"
}

// also - Side effects, return self
val user = User().also {
    logger.log("Created user: ${it.id}")
}

Extensions

// ✅ Extension functions
fun String.isValidEmail(): Boolean {
    return android.util.Patterns.EMAIL_ADDRESS.matcher(this).matches()
}

// ✅ Extension properties
val Context.screenWidth: Int
    get() = resources.displayMetrics.widthPixels

// Usage
if (email.isValidEmail()) { ... }
val width = context.screenWidth

Lifecycle Patterns

ViewModel

class HomeViewModel(
    private val repository: HomeRepository,
    savedStateHandle: SavedStateHandle
) : ViewModel() {

    private val _state = MutableStateFlow(HomeState())
    val state: StateFlow<HomeState> = _state.asStateFlow()

    init {
        loadData()
    }

    private fun loadData() {
        viewModelScope.launch {
            _state.update { it.copy(isLoading = true) }

            repository.getItems()
                .onSuccess { items -> _state.update { it.copy(items = items, isLoading = false) } }
                .onFailure { error -> _state.update { it.copy(error = error.message, isLoading = false) } }
        }
    }
}

Lifecycle-aware Collection

@Composable
fun HomeScreen(viewModel: HomeViewModel = koinViewModel()) {
    val state by viewModel.state.collectAsStateWithLifecycle()

    HomeContent(state = state)
}

Functional Patterns

Result Type

// ✅ Use Result for operations that can fail
suspend fun fetchUser(id: String): Result<User> = runCatching {
    api.getUser(id).toDomain()
}

// ✅ Chain operations
repository.fetchUser(id)
    .map { it.profile }
    .mapCatching { decryptProfile(it) }
    .onSuccess { displayProfile(it) }
    .onFailure { showError(it) }

Higher-Order Functions

// ✅ Pass functions as parameters
fun <T> retry(
    times: Int,
    block: suspend () -> T
): T {
    repeat(times - 1) {
        try { return block() }
        catch (e: Exception) { delay(1000) }
    }
    return block() // Last attempt
}

// Usage
val result = retry(3) { api.fetchData() }

Sealed Classes

sealed interface UiState<out T> {
    data object Loading : UiState<Nothing>
    data class Success<T>(val data: T) : UiState<T>
    data class Error(val message: String) : UiState<Nothing>
}

// Exhaustive when
when (state) {
    is UiState.Loading -> LoadingIndicator()
    is UiState.Success -> Content(state.data)
    is UiState.Error -> ErrorMessage(state.message)
}

Resource Management

Context Extensions

fun Context.dp(value: Int): Int = 
    (value * resources.displayMetrics.density).toInt()

fun Context.showToast(message: String) {
    Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}

String Resources

// strings.xml
<string name="welcome_message">Welcome, %1$s!</string>

// Usage
stringResource(R.string.welcome_message, userName)

Remember: Kotlin is concise. Embrace its idioms for cleaner, safer code.