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初心者がメモアプリ実装でつまずいた3つの壁とその乗り越え方

Posted at

はじめに

こんにちは!
先日公開した詳細設計の記事をもとに、実際にシンプルなメモアプリを実装してみました。

完成したアプリがこちらです!シンプルな見た目ですが、モダンなAndroid開発の基本が詰まっています。

スクリーンショット スクリーンショット

この記事では、設計書から実際に動くアプリを完成させるまでの具体的な実装ステップと、その過程で僕が盛大につまずいた3つのポイント、そしてそれをどう解決したかを正直に記録していこうと思います。

Composeを学び始めた方や、同じようなエラーに遭遇した方の助けになれば嬉しいです!


Step 1: プロジェクトの土台を固める(データ層とViewModelの実装)

何事もまずは土台から、ということで、UIには触らずにアプリの裏側から実装を始めました。

具体的には、

  • メモのデータを定義するMemo.kt
  • UIの状態を定義するMemoUiState.kt
  • 全てのロジックを司るMemoViewModel.kt

この3つのファイルを、先に詳細設計書通りに実装しました。

最初のつまずき:「LocalDateTime.now()が使えない!」問題

よし、データクラスは完璧だ!と思った矢先、LocalDateTime.now()の部分で早速エラーが発生しました(笑)。

  • エラー内容: Call requires API level 26 (current min is 24)

  • 原因調査: 調べてみたところ、java.time.LocalDateTimeはJava 8で導入されたAPIで、AndroidではAPIレベル26 (Android 8.0)以上でないと標準でサポートされていない、というのが原因でした。僕のプロジェクトのminSdkは24だったので、古いOSではこの機能が使えなかったんですね。

  • 解決策: **コアライブラリの脱糖(Desugaring)**という仕組みを利用しました。app/build.gradle.ktsに以下の設定を追加することで、古いOSでもJava 8のAPIが使えるようになります。

    // build.gradle.kts
    
    android {
        // ...
        compileOptions {
            sourceCompatibility = JavaVersion.VERSION_1_8
            targetCompatibility = JavaVersion.VERSION_1_8
            isCoreLibraryDesugaringEnabled = true
        }
    }
    
    dependencies {
        // ...
        coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4")
    }
    

    これで無事にビルドが通りました。いやー、いきなりAndroidのバージョン互換性の洗礼を受けましたね...。


Step 2: @Preview駆動でUI部品を実装する

次に、Composeの強力な機能である@Previewを使い倒して、UIの部品を一つずつ作っていきました。
MemoItem(リストの1行)やMemoInputSection(入力エリア)などを、アプリを実行せずにプレビューだけで見た目を確認しながら実装できるのは、本当に快適でした。

2番目のつまずき:「by rememberが動かない!」問題

MemoInputSectionで、テキスト入力の状態を保持するためにvar text by remember { mutableStateOf("") }と書いたところで、大量のエラーが発生しました。

  • エラー内容: Property delegate must have a 'getValue(...)' method.など

  • 原因調査: 最初はrememberの使い方が間違っているのかと思いましたが、これも単純な**import漏れ**が原因でした。byキーワードで状態管理を移譲(delegate)するには、getValuesetValueという関数が必要で、それらを明示的にimportする必要があったのです。

  • 解決策: ファイルの先頭に、以下の2行を追加することで全て解決しました。

    // ...
    import androidx.compose.runtime.getValue
    import androidx.compose.runtime.setValue
    // ...
    

    Composeの状態管理の裏側を少し垣間見た気がしました。


Step 3: ViewModelとUIの神経接続、そして完成へ

最後に、完成したUI部品とViewModelをMemoScreen.ktで合体させ、MainActivity.ktから呼び出す、という最終工程です。

3番目のつまずき:「viewModel()関数が見つからない!」問題

いよいよViewModelをUIに接続しようとval viewModel: MemoViewModel = viewModel()と書いたところで、viewModel()Unresolved referenceエラーに。

  • エラー内容: Unresolved reference: viewModel

  • 原因調査: importは正しくできているのになぜ?と悩んだのですが、これは**「レシピ名(import)は書いたけど、レシピ本(ライブラリ)を本棚に入れていない」**状態でした。viewModel()という便利な関数は、専用のライブラリを追加しないと使えなかったのです。

  • 解決策: app/build.gradle.ktsdependenciesブロックに、以下のViewModelとComposeを連携させるためのライブラリを追加しました。

    // build.gradle.kts
    dependencies {
        // ...
        implementation(libs.androidx.lifecycle.viewmodel.compose)
    }
    

    Syncしたら、無事にエラーが消えました。依存関係の管理は、プロジェクトの土台として本当に重要だと再認識しました。


まとめと今後の展望

というわけで、いくつかの壁にぶつかりながらも、無事にシンプルなメモアプリを完成させることができました!

今回の実装を通して、

  • ComposeのUI構築と状態管理の基本
  • Androidのバージョン互換性の考慮
  • 依存関係の解決

といった、実務に直結する多くのことを学べた気がします。
今後は、このアプリにRoomを使ったデータベース保存機能を追加することに挑戦していく予定です!

ここまで読んでいただきありがとうございました!

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?