Android kotlin Retrofit

Retrofit

Retrofit is simple HTTP Client Android and Java by square.

Simple use and follow callback style, compare to Async task, code becomes shorter.

Server side preparation

In this time, I prepared following API (on local) by golang (I just put the codes on the bottom of this entry)

GET : http://localhost:8000/users/{id} -> Return one user object by json

GET : http://localhost:8000/list -> Return user list object

POST : http://localhost:8000/post Body {id: “ss”} -> Return success object {success : true}

How to use retrofit

Add dependencies to build.gradle

build.gradle

android {
   compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = "1.8"
    }
}

dependencies {
   implementation 'com.squareup.retrofit2:retrofit:2.8.1'
   implementation 'com.squareup.retrofit2:converter-gson:2.8.1'
}

converter-gson is json -> object converter powered by google

NetworkService.kt

This is Service interface codes. To use Retrofit, we need to prepare service (definition of API call)

package com.daiji110.retrofitsample.service

import com.daiji110.retrofitsample.model.Success
import com.daiji110.retrofitsample.model.User
import retrofit2.Call
import retrofit2.http.*

interface NetworkService {

    @GET("/users/{id}")
    fun getUser(@Path("id") id: String) : Call<User>

    @GET("/list")
    fun getList() : Call<List<User>>

    @Headers(
        "User-Agent:Retrofit-Sample-App")
    @POST("post")
    fun post(@Body id: String) : Call<Success>

}

User.kt

This is response model. Retrofit converts json to Object using converter

data class User(val id: String, val name: String, val age: Int)

Success.kt

data class Success(val success: Boolean)

MainActivity.kt

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)


        val retrofit : Retrofit = Retrofit.Builder()
            .baseUrl("http://10.0.2.2:8000/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
        val service : NetworkService = retrofit.create(NetworkService::class.java)

        // Sync : Need to call not main thread
/*
        val response = service.getUser("1").execute()
        if (response.isSuccessful) {
            Log.d("Sync", response.body().toString())
        }
*/
        // Async
        service.getUser("1").enqueue(object : Callback<User> {
            override fun onFailure(call: Call<User>, t: Throwable) {
                Log.w("Error", t.message)
            }

            override fun onResponse(call: Call<User>, response: Response<User>) {
                Log.d("ASync", response.body().toString())
                response.body()?.let {
                    Log.d("Name", it.name)
                    Log.d("Age", it.age.toString())
                    Log.d("ID", it.id.toString())
                }
            }
        })

        // Async list return
        service.getList().enqueue(object: Callback<List<User>> {
            override fun onFailure(call: Call<List<User>>, t: Throwable) {
                Log.w("Error", t.message)
            }
            override fun onResponse(call: Call<List<User>>, response: Response<List<User>>) {
                response.body()?.let {
                    it.forEach {
                        Log.d("Name", it.name)
                        Log.d("Age", it.age.toString())
                        Log.d("ID", it.id.toString())
                    }
                }
            }
        })

        // Post
        service.post("33").enqueue(object: Callback<Success> {
            override fun onFailure(call: Call<Success>, t: Throwable) {
                Log.w("Error", t.message)
            }

            override fun onResponse(call: Call<Success>, response: Response<Success>) {
                response.body()?.let {
                    Log.d("Res", it.toString())
                }
            }
        })
    }

}

Golang code

This is server side codes to support this.

I don’t explain about this details in this time

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/gorilla/mux"
)

type User struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
	ID   string `json:"id"`
}

type Res struct {
	Success bool `json:"success"`
}

/*
 *  Routing
 */
func users(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	id := vars["id"]

	person := User{
		Name: "Jiro",
		Age:  18,
		ID:   id,
	}
	json.NewEncoder(w).Encode(person)
}

func list(w http.ResponseWriter, r *http.Request) {
	user1 := User{
		Name: "Taro",
		Age:  18,
		ID:   "111111",
	}
	user2 := User{
		Name: "Jiro",
		Age:  30,
		ID:   "222222",
	}
	user3 := User{
		Name: "Santa",
		Age:  55,
		ID:   "333333",
	}
	var s []User
	s = append(s, user1, user2, user3)
	json.NewEncoder(w).Encode(s)
}

func POSTHandle(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
	defer r.Body.Close()
	body, err := ioutil.ReadAll(r.Body)
	fmt.Println(body)
	res := Res{
		Success: true,
	}
	if err != nil {
		res.Success = false
	}
	json.NewEncoder(w).Encode(res)
}

func main() {
	router := mux.NewRouter()
	router.HandleFunc("/users/{id}", users)
	router.HandleFunc("/list", list)
	router.HandleFunc("/post", POSTHandle).Methods("POST")
	http.ListenAndServe(":8000", router)
}

Android
スポンサーリンク
Professional Programmer2

コメント