DAY 6

DAY 6

반응형

Retrofit을 사용한 통신

1. 의존성 추가

implementation 'com.squareup.retrofit2:retrofit:2.9.0'

implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

implementation "com.squareup.okhttp3:logging-interceptor:4.8.1"

참고로 의존성 버전확인은 Project Structure > dependencies에서 확인할 수 있습니다.

의존성 추가 한후 sync now 해줍니다.

2. 인터넷 사용 허용

3가지 구성요소

Interface

Retrofit.Builder

DTO (POJO)

4. 전체소스 소스

IRetrofit.kt : Interface에 해당

package intergrated.coordi.retrofit_test import com.google.gson.JsonElement import retrofit2.Call import retrofit2.http.Field import retrofit2.http.FormUrlEncoded import retrofit2.http.POST interface IRetrofit { @FormUrlEncoded @POST("/login") fun loginRequest( @Field("username") username:String, @Field("password") password:String ): Call }

RetrofitClient.kt Retrofit.Builder에 해당

package intergrated.coordi.retrofit_test import android.util.Log import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import java.util.concurrent.TimeUnit object RetrofitClient { private var retrofitClient:Retrofit? = null private val TAG = "로그" fun getClient(baseUrl:String) : Retrofit?{ if(retrofitClient == null){ val client = OkHttpClient.Builder() val loggingInterceptor =HttpLoggingInterceptor(object:HttpLoggingInterceptor.Logger{ override fun log(message: String) { Log.d(TAG,"RetrofitClient - log : ${message}") } }) loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY) client.addInterceptor(loggingInterceptor) client.connectTimeout(10, TimeUnit.SECONDS) client.readTimeout(10, TimeUnit.SECONDS) client.writeTimeout(10, TimeUnit.SECONDS) client.retryOnConnectionFailure(true) retrofitClient =Retrofit.Builder() .baseUrl(baseUrl) .addConverterFactory(GsonConverterFactory.create()) .client(client.build()) .build() } return retrofitClient; } }

RetrofitManager.kt

package intergrated.coordi.retrofit_test import android.util.Log import com.google.gson.JsonElement import retrofit2.Call import retrofit2.Callback import retrofit2.Response class RetrofitManager { private val baseUrl = "http://192.168.21.126:5000" private val TAG = "로그" companion object{ val instance = RetrofitManager() } private val iRetrofit: IRetrofit? = RetrofitClient.getClient(baseUrl)?.create(IRetrofit::class.java) fun loging(username:String, password:String, completion:(LoginResponse, String)->Unit){ var call = iRetrofit?.loginRequest(username, password) ?:return call.enqueue(object: Callback { override fun onResponse(call: Call, response: Response) { Log.d(TAG, "RetrofitManager - onResponse body : ${response.body()}") Log.d(TAG, "RetrofitManager - onResponse code : ${response.code()}") if(response.code() == 200){ completion(LoginResponse.OK, response.body().toString()) }else{ completion(LoginResponse.FAIL, response.body().toString()) } } override fun onFailure(call: Call, t: Throwable) { Log.d(TAG, "RetrofitManager - onFailure") completion(LoginResponse.FAIL, t.toString()) } }) } }

MainActivity.kt

package intergrated.coordi.retrofit_test import androidx.appcompat.app.AppCompatActivity import androidx.databinding.DataBindingUtil import android.os.Bundle import android.os.PersistableBundle import android.util.Log import androidx.appcompat.app.AlertDialog import intergrated.coordi.retrofit_test.databinding.ActivityMainBinding class MainActivity:AppCompatActivity(){ private lateinit var binding:ActivityMainBinding private val TAG = "로그" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = DataBindingUtil.setContentView(this, R.layout.activity_main) binding.user = User("pepper","123123") binding.loginButton.setOnClickListener{ Log.d(TAG,"MainActivity login button click"); var username = binding.usernameInput.text.toString() var password = binding.passwordInput.text.toString() loginRequest(username, password) } } private fun loginRequest(username: String, password: String) { var dialogBuilder =AlertDialog.Builder(this@MainActivity) if(username.isEmpty() || password.isEmpty()){ dialogBuilder.setTitle("알림") dialogBuilder.setMessage("빈 칸을 전부 채워주세요") dialogBuilder.setPositiveButton("확인",null) dialogBuilder.show() }else{ RetrofitManager.instance.loging( username = username, password = password, completion ={loginResponse, response -> when(loginResponse){ LoginResponse.FAIL->{ dialogBuilder.setTitle("알림") dialogBuilder.setMessage("로그인 실패") dialogBuilder.setPositiveButton("확인",null) dialogBuilder.show() } LoginResponse.OK->{ dialogBuilder.setTitle("알림") dialogBuilder.setMessage("로그인 성공") dialogBuilder.setPositiveButton("확인",null) dialogBuilder.show() } } } ) } } } data class User(val name:String, val pass:String);

activity_main.xml

***

val name: String = nm ?: "" //nm라는 변수가null 이면 name에 ""가 들어감

object

싱글턴 클래스로 만들 때

익명 클래스 객체를 생성할 때

*** 참고 Retrofit API Declaration

API Declaration

Annotations on the interface methods and its parameters indicate how a request will be handled.

REQUEST METHOD

Every method must have an HTTP annotation that provides the request method and relative URL. There are eight built-in annotations: HTTP, GET, POST, PUT, PATCH, DELETE, OPTIONS and HEAD. The relative URL of the resource is specified in the annotation.

@GET("users/list")

You can also specify query parameters in the URL.

@GET("users/list?sort=desc")

URL MANIPULATION

A request URL can be updated dynamically using replacement blocks and parameters on the method. A replacement block is an alphanumeric string surrounded by { and }. A corresponding parameter must be annotated with @Path using the same string.

@GET("group/{id}/users")

Call> groupList(@Path("id") int groupId);

Query parameters can also be added.

@GET("group/{id}/users")

Call> groupList(@Path("id") int groupId, @Query("sort") String sort);

For complex query parameter combinations a Map can be used.

@GET("group/{id}/users")

Call> groupList(@Path("id") int groupId, @QueryMap Map options);

REQUEST BODY

An object can be specified for use as an HTTP request body with the @Body annotation.

@POST("users/new")

Call createUser(@Body User user);

The object will also be converted using a converter specified on the Retrofit instance. If no converter is added, only RequestBody can be used.

FORM ENCODED AND MULTIPART

Methods can also be declared to send form-encoded and multipart data.

Form-encoded data is sent when @FormUrlEncoded is present on the method. Each key-value pair is annotated with @Field containing the name and the object providing the value.

@FormUrlEncoded

@POST("user/edit")

Call updateUser(@Field("first_name") String first, @Field("last_name") String last);

Multipart requests are used when @Multipart is present on the method. Parts are declared using the @Part annotation.

@Multipart

@PUT("user/photo")

Call updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);

Multipart parts use one of Retrofit's converters or they can implement RequestBody to handle their own serialization.

HEADER MANIPULATION

You can set static headers for a method using the @Headers annotation.

@Headers("Cache-Control: max-age=640000")

@GET("widget/list")

Call> widgetList();

@Headers({

"Accept: application/vnd.github.v3.full+json",

"User-Agent: Retrofit-Sample-App"

})

@GET("users/{username}")

Call getUser(@Path("username") String username);

Note that headers do not overwrite each other. All headers with the same name will be included in the request.

A request Header can be updated dynamically using the @Header annotation. A corresponding parameter must be provided to the @Header. If the value is null, the header will be omitted. Otherwise, toString will be called on the value, and the result used.

@GET("user")

Call getUser(@Header("Authorization") String authorization)

Similar to query parameters, for complex header combinations, a Map can be used.

@GET("user")

Call getUser(@HeaderMap Map headers)

He

from http://paulaner80.tistory.com/200 by ccl(A) rewrite - 2021-12-24 12:02:00