a-4-2-2.Retrofit2を使ったPOSTのAPIアクセス

### a-4-2-2.Retrofit2を使ったPOSTのAPIアクセス

#### 目標設定
[一覧に戻る](https://qiita.com/ryouta33/items/57f5e51a26086151a0da)

#### 課題
3. Retrofit2でPOSTメソッドのAPIの呼び出しができるか。
3. Retrofit2のPOSTメソッドで呼び出しのBodyを取得できるか。

#### Github

https://github.com/wakizaka24/AndroidTest

#### テスト実装

```kotlin:Retrofit2TestActivity.kt
class Retrofit2TestActivity : AppCompatActivity() {
    private lateinit var binding: ActivityRetrofit2TestBinding
    private var retrofit2TestService: Retrofit2TestService = Retrofit2TestService()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityRetrofit2TestBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)

        ...

        binding.postingApiButton.stateListAnimator = null
        binding.postingApiButton.setOnClickListener {
            // 1. Retrofit2でPOSTメソッドのAPIの呼び出しができるか。
            // ・可能でした。
            val body = Retrofit2TestService.Api3RequestBody(
                values = arrayOf(
                    Retrofit2TestService.Api3RequestTable1Value(
                        3, "Value 33333!"
                    )
                ))
            retrofit2TestService.getApiAccess().postTest1Table(body)
                .enqueue(object : Callback<Void> {
                    override fun onResponse(
                        call: Call<Void>,
                        response: Response<Void>
                    ) {
                        if (response.raw().code() == 200) {
                            showMessage("データの追加に成功しました")
                        } else {
                            showMessage(response.errorBody()?.string() ?: "APIエラー")
                        }
                    }

                    override fun onFailure(
                        call: Call<Void>,
                        t: Throwable
                    ) {
                        Log.d("Retrofit2TestActivity", t.message ?: "APIエラー")
                    }
                })
        }

        ...
    }
    fun showMessage(message: String) {
        val builder = AlertDialog.Builder(this)
        builder.setTitle("Retrofit2の検証")
            .setMessage(message)
            .setPositiveButton("OK") { _, _ ->

            }
        builder.create()
        builder.show()
    }
}
```

```xml:activity_retrofit2_test.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <LinearLayout
        android:id="@+id/linear_layout1"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_marginStart="8dp"
        android:layout_marginTop="4dp">

        <TextView
            android:id="@+id/text_1_text_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="0dp"
            android:text="Retrofit2の検証"
            android:textSize="21sp"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:ignore="HardcodedText" />

        <Space
            android:layout_width="match_parent"
            android:layout_height="4dp" />

        <LinearLayout
            android:id="@+id/linear_layout2"
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <Button
                android:id="@+id/getting_api_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/style3_button_background"
                app:backgroundTint="@null"
                android:text="GETの\nAPIアクセス"
                android:padding="8dp"
                android:textSize="11sp"
                tools:ignore="HardcodedText" />

            <Space
                android:layout_width="4dp"
                android:layout_height="match_parent" />

            <Button
                android:id="@+id/posting_api_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/style3_button_background"
                app:backgroundTint="@null"
                android:text="POSTの\nAPIアクセス"
                android:padding="8dp"
                android:textSize="11sp"
                tools:ignore="HardcodedText" />
        </LinearLayout>

        <Space
            android:layout_width="match_parent"
            android:layout_height="4dp" />

        <Button
            android:id="@+id/deleting_api_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/style3_button_background"
            app:backgroundTint="@null"
            android:text="DELETEの\nAPIアクセス"
            android:padding="8dp"
            android:textSize="11sp"
            tools:ignore="HardcodedText" />
    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
```

```kotlin:Retrofit2TestService.kt
class Retrofit2TestService {
    interface APIInterface {
        // 2. Retrofit2のPOSTメソッドで呼び出しのBodyを取得できるか。
        // ・可能でした。
        @POST("api3_post_test1_table.php")
        fun postTest1Table(@Body body: Api3RequestBody): Call<Void>
        ...
    }
    ...
    data class Api3RequestBody(
            @SerializedName("table1_values") val values:
            Array<Api3RequestTable1Value>
        ): Serializable {
        override fun equals(other: Any?): Boolean {
            if (this === other) return true
            if (javaClass != other?.javaClass) return false

            other as Api3RequestBody

            if (!values.contentEquals(other.values)) return false

            return true
        }

        override fun hashCode(): Int {
            return values.contentHashCode()
        }
    }
    data class Api3RequestTable1Value(
        @SerializedName("COLUM1") val colum1: Int,
        @SerializedName("COLUM2") val colum2: String
    ): Serializable
    ...
    companion object {
        private const val BASE_URL = "https://wakizaka24.sakura.ne.jp/reversi/php/"
    }

    private var apiInterfaceImpl: APIInterface

    init {
        val gsonFactory = GsonConverterFactory.create(
            GsonBuilder().serializeNulls().create())
        val retrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(gsonFactory)
            .build()
        apiInterfaceImpl = retrofit.create(APIInterface::class.java)
    }

    fun getApiAccess(): APIInterface {
        return apiInterfaceImpl
    }
}
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545849/1b421309-9c30-8c49-25ca-0fe932379fe7.png" width="300" />

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545849/9b0b65c3-f3d1-d8fa-f92c-04cd190e443f.png" width="300" />