on
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