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?

【Hilt + Retrofit】Androidアプリにネットワーキング層を実装する完全ガイド(MockAPI利用)

Posted at

これまで私たちのメモアプリは、すべてのデータがスマホの中だけで完結していました。Day 2の今日は、このアプリをインターネットの世界に接続し、クラウド上のサーバーと通信するための「神経系(ネットワーキング層)」を構築します。

このステップをマスターすれば、あなたは「クライアント・サーバー型」アプリ開発者として大きな一歩を踏み出すことになります。

今回は、サーバー開発の手間を省くため、偽物のサーバーを簡単に作れるMockAPIというサービスを「練習相手」として利用します。

1. 今回のゴール (要件定義)

  • 目的: Androidアプリが、リモートサーバー(MockAPI)と通信するための、再利用可能で堅牢なネットワーキング層を構築する。
  • スコープ:
    • やること: Retrofitの導入、API仕様の定義、Hiltによる依存性注入、そして最初の通信テストまで。
    • やらないこと: この通信機能を実際のUIに反映させること(それはDay 3以降のタスクです)。

2. 全体像の設計 (基本設計)

  • アーキテクチャ: 既存のMVVMアーキテクチャを拡張し、Repositoryが新設するApiServiceを通じてサーバーと通信できるようにします。
  • コンポーネント:
    • networkパッケージを新設し、通信関連のコードを集約します。
    • DTO (Data Transfer Object): サーバーとの通信専用のデータクラス(例: MemoResponse)を作成します。
    • ApiService: サーバーのAPIエンドポイント(URL)と通信方法(GET, POSTなど)を定義するインターフェースです。
    • Hiltモジュール: RetrofitApiServiceといった、アプリ全体で共有する通信部品の作り方をHiltに教えます。

3. 詳細設計 & 実装ステップ

ここからは、具体的なコードと共に実装手順を詳細に解説します。

Step 1: サーバーの準備 (MockAPIのセットアップ) (約30分)

🎯 目標: 通信の相手となる、練習用のサーバー(API)を用意する。

👨‍💻 作業内容:

  1. MockAPI.io にアクセスし、アカウントを作成します。
  2. userリソースの作成:
    • Resource Name: user
    • Schema: email (String), password (String) を追加してCreate。
  3. memoリソースの作成:
    • Resource Name: memo
    • Schema: title (String), content (String), createdAt (Date), updatedAt (Date), userId (String) を追加してCreate。
  4. APIのURLを控える:
    • 画面上部に表示されている https://xxxxxxxx.mockapi.io/api/v1/ のようなURLをコピーしておきます。

Step 2: 依存関係の追加 (Gradle設定) (約30分)

🎯 目標: サーバーと通信するためのライブラリ「Retrofit」をプロジェクトに追加する。

👨‍💻 作業内容:

app/build.gradle.ktsを開き、dependenciesブロックに以下のライブラリを追記し、「Sync Now」をクリックします。

app/build.gradle.kts
dependencies {

    // ... (HiltやComposeの依存関係) ...

    // ★★★ 以下を追記 ★★★

    // Retrofit (本体)
    implementation("com.squareup.retrofit2:retrofit:2.9.0")

    // kotlinx.serialization と Retrofit を連携させるためのコンバータ
    implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0")

    // 通信の詳細なログを見るためのインターセプタ (デバッグに超便利)
    implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")

}

Step 3: API仕様の定義 (通信のルール作り) (約1.5時間)

🎯 目標: MockAPIの仕様に合わせて、通信用のデータクラス(DTO)と、通信メソッド(エンドポイント)を定義したインターフェースを作成する。

👨‍💻 作業内容:

  1. com.example.simplememoapp_androidの下にnetworkパッケージを、さらにその下にdtoパッケージを新設します。
  2. dtoパッケージにMemoResponse.ktを作成します。
  3. networkパッケージにApiService.ktを作成します。
network/dto/MemoResponse.kt (新規作成)
package com.example.simplememoapp_android.network.dto

import kotlinx.serialization.Serializable

@Serializable
data class MemoResponse(
    val id: String,
    val createdAt: String,
    val title: String,
    val content: String,
    val updatedAt: String,
    val userId: String
)

【ポイント】: これはDB用のMemoクラスとは別物です。サーバーとの通信専用のデータ形式なので、dto (Data Transfer Object) と呼びます。

network/ApiService.kt (新規作成)
package com.example.simplememoapp_android.network

import com.example.simplememoapp_android.network.dto.MemoResponse
import retrofit2.http.GET
import retrofit2.http.Path

interface ApiService {

    // 例: .../users/{userId}/memos というURLにGETリクエストを送る
    @GET("users/{userId}/memos")
    suspend fun getMemosForUser(@Path("userId") userId: String): List<MemoResponse>

    // 今後、ログイン用のPOSTや、メモ作成用のPOSTなどもここに追加していく
}

Step 4: Hiltモジュールの拡張 (DIの設定) (約30分)

🎯 目標: Hiltに「Retrofitの作り方」を教え、アプリのどこからでも使えるようにする。

👨‍💻 作業内容:

di/AppModule.ktを開き、RetrofitとApiServiceのインスタンスを生成するための@Provides関数を追記します。

di/AppModule.kt (追記)
// ... import文を追加 ...

import com.example.simplememoapp_android.network.ApiService
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit

@Module
@InstallIn(SingletonComponent::class)
object AppModule {

    // ... (Database, Dao, RepositoryのProvides関数) ...

    // ★★★ 以下を追記 ★★★

    @Provides
    @Singleton
    fun provideOkHttpClient(): OkHttpClient {
        return OkHttpClient.Builder()
            // 通信のログをLogcatに出力するための設定
            .addInterceptor(HttpLoggingInterceptor().apply {
                level = HttpLoggingInterceptor.Level.BODY
            })
            .build()
    }

    @Provides
    @Singleton
    fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
        val contentType = "application/json".toMediaType()
        // kotlinx.serializationがJsonのパースで厳格すぎるとエラーになる場合があるため、設定を緩める
        val json = Json { ignoreUnknownKeys = true }

        return Retrofit.Builder()
            .baseUrl("https://xxxxxxxx.mockapi.io/api/v1/") // ★ Step1で控えたあなたのURLに書き換える!
            .client(okHttpClient)
            .addConverterFactory(json.asConverterFactory(contentType))
            .build()
    }

    @Provides
    @Singleton
    fun provideApiService(retrofit: Retrofit): ApiService {
        return retrofit.create(ApiService::class.java)
    }
}

【注意】
baseUrlには、Step 1で控えたあなた専用のMockAPIのURLを必ず設定してください。

Step 5: 動作確認 (最初の通信テスト) (約30分)

🎯 目標: UIはまだないが、バックエンドとの神経系が正しく繋がったかをLogcatで確認する。

👨‍💻 作業内容:

  1. MemoRepositoryMemoListViewModelに一時的なテストコードを埋め込みます。
di/AppModule.kt (一時的な修正)
// ...

@Provides
@Singleton
// ★引数にapiServiceを追加
fun provideMemoRepository(dao: MemoDao, apiService: ApiService): MemoRepository {
    // ★apiServiceを渡す
    return MemoRepository(dao, apiService)
}
data/repository/MemoRepository.kt (一時的な修正)
// ★コンストラクタにapiServiceを追加
class MemoRepository(
    private val memoDao: MemoDao,
    private val apiService: ApiService
) {

    // ...

    // ★テスト用メソッドを追加
    suspend fun checkApiStatus() {
        apiService.getMemosForUser("1")
    }
}
ui/viewmodel/MemoListViewModel.kt (一時的な修正)
// ...

import android.util.Log

@HiltViewModel
class MemoListViewModel @Inject constructor(
    private val repository: MemoRepository
) : ViewModel() {

    // ...

    init {
        // ★テスト用のコードをinitブロックに追加
        viewModelScope.launch {
            try {
                Log.d("APITEST", "APIへの接続テストを開始します...")
                repository.checkApiStatus()
                Log.d("APITEST", "APIへの接続に成功しました!")
            } catch (e: Exception) {
                Log.e("APITEST", "APIへの接続に失敗しました: ${e.message}")
            }
        }
    }

    // ...

}
  1. アプリを実行し、Android StudioのLogcatAPITESTと検索します。APIへの接続に成功しました!と表示され、その前にOkHttpのログ(JSONデータなど)が出力されていれば、今日のタスクは完全成功です。

  2. 【重要】 動作確認が終わったら、MemoListViewModelinitブロックに追加したテストコードは必ず削除してください。

お疲れ様でした!これでDay 2のタスクは完了です。あなたのアプリは、サーバーと会話する能力を手に入れました。

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?