0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JetPack Composeについて学んだことを徒然なるままに書いていく # フォルダ構成編

Last updated at Posted at 2025-04-04

はじめに

Jetpack Composeについて学びたいと思ったので、勉強がてら名刺アプリを個人開発してみました。その時に検討した内容を備忘録的に書いていきます。
この記事では、フォルダ構成検討時に学んだこととを書いてます。(時間があれば他のことも書いてみる予定)

アーキテクチャーとフォルダ構成

Kotlinは、MVVM(Model/View/ViewModel)が主流のようなのでそのまま採用します。
ただ、UIロジックを分離させないとViewModel層がかなり肥大化するので、そこを考慮した上でフォルダ構成を考えてみました。

フォルダ構成

/app
├── /src
│   ├── /main
│   │   ├── /java/com/example/app
│   │   │   ├── /data
│   │   │   │   ├── /model
│   │   │   │   │   └── BusinessCard.kt
│   │   │   │   ├── /repository
│   │   │   │   │   └── BusinessCardRepository.kt
│   │   │   │   └── /network
│   │   │   │       └── BusinessCardNetwork.kt
│   │   │   ├── /domain
│   │   │   │   └── /usecase
│   │   │   │       └── RegisterBusinessCardUseCase.kt
│   │   │   ├── /ui
│   │   │   │   ├── /screen
│   │   │   │   │   ├── /home
│   │   │   │   │   │   ├── HomeScreen.kt
│   │   │   │   │   │   └── HomeViewModel.kt
│   │   │   │   │   ├── /detail
│   │   │   │   │   │   ├── DetailScreen.kt
│   │   │   │   │   │   └── DetailViewModel.kt
│   │   │   │   │   └── /profile
│   │   │   │   │   │   ├── ProfileScreen.kt
│   │   │   │   │   │   └── ProfileViewModel.kt
│   │   │   │   └── /component
│   │   │   │       ├── CustomButton.kt
│   │   │   │       └── CustomCard.kt
│   │   │   ├── /di
│   │   │   │   └── AppModule.kt
│   │   │   ├── /navigation
│   │   │   │   └── AppNavigation.kt
│   │   │   ├── /util
│   │   │   │   └── Constants.kt
│   │   │   └── MainActivity.kt
│   │   └── /res
│   │       └── /image
│   │       └── /icon
│   │       └── /values

フォルダごとの役割

ここではそれぞれの役割について簡単に説明します。

Data層

フォルダ名 説明
model データ型を管理する
repository データの取得先・取得方法を管理する
network API通信などを管理する

Domain層

フォルダ名 説明
usecase ビジネスロジックを管理する

UI層

フォルダ名 説明
screen 画面を管理する同じ階層にViewModelファイルも配置する
component ボタンやダイアログなどのパーツを管理する

DI層 (Dependency Injection)

フォルダ名 説明
di 依存性の注入(Repository、ViewModelなどをまとめて組み立てる)

Navigation層

フォルダ名 説明
navigation 画面遷移を管理する

Util層

フォルダ名 説明
util よく使う定数や関数を管理

Res層

フォルダ名 説明
image 画像を管理する
icon アイコンを管理する
values 色や文字サイズを管理する

フォルダ構成検討時に学んだこと

1、UI 層は「画面」と「コンポーネント」を分離する

UI のロジックは Composableアノテーションを使って呼び出すらしいので、再利用できるパーツは componentフォルダに分離しておくことで「画面」と「ロジック」をスッキリさせました。

例:Composeアノテーションの使い方

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyApplicationTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    HomeScreen(Home().text())
                }
            }
        }
    }
}

@Composable
fun HomeScreen(text: String) {
    Text(text = text)
}

2、ViewModelの状態管理にStateとFlowを使う

Stateは聴き馴染みがありましたが、Flowは初めて知りました。

State: 現在の状態を表すオブジェクト。UIがどのようなデータを表示するか、またはどのような状態(読み込み中、エラー中、成功した状態など)であるかを管理してる
Flow: データのストリームを提供するKotlinの機能らしい。非同期でデータを受け取り続けることができるのでデータの変化を監視できる。


3、sealed classでUIの状態 (Loading, Success, Error) を管理する

sealed class(シールドクラス)は、例えば、以下のようなUIの状態を管理できるらしい。
Loading: データを読み込んでいる最中
Success: データの取得が成功した状態
Error: データの取得に失敗した状態


4、ビジネスロジックの考え方

ビジネスロジックは、pureなJava(Kotlin)で実装してフレームワークなどに依存しない作りにした方がよい。
将来的にフレームワークを変更する必要が出てきた時に移行することが容易になり、ビジネスロジックをそのまま使える。

まとめ

小規模〜中規模:ちょっと工夫は必要だけど、基本的にはMVVM構成でよさそう
大規模:クリーンアーキテクチャーを採用したい
マルチプラットフォーム:Modelにビジネスロジックを集約し、異なるプラットフォームでも再利用しやすい構成になっているMVI(Model-View-Intent)がいいのかも?

という感じで、フォルダ構成を検討するだけでも、いろんな考え方、やり方があるんだなと大変勉強になりました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?