Retrofit으로 통신해보기
소개
Retrofit2는 안드로이드 REST API 통신 라이브러리입니다. 통신 라이브러리중 Volley와 함께 가장 많이 사용되는 라이브러리입니다.
Retrofit을 사용한 이유는 성능과 간단한 구현, Type-Safe때문입니다.
소개는 여기까지하고 바로 구현으로 들어가겠습니다.
구현
Retrofit을 사용하려면 세 가지 클래스가 필요합니다.
- JSON형태의 모델클래스
- HTTP 작업을 정의하는 (onSuccess/onFail) 인터페이스
- Retrofit.Builder를 선언한 클래스(baseUrl과 Converter등을 선언, Interceptor를 추가하여 응답을 가공할 수도 있다.)
1. Empty Activity생성. (API Level 30)
2. build.gradle 수정
Retrofit, Picasso, Gson의 의존성을 추가합니다.
dependencies{
//의존성 추가
implementation 'com.squareup.picasso:picasso:2.5.2'
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'
}
3. AndroidManifest.xml 수정
Manifest에서 Internet도 허용해줍니다.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.retrofittest">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.RetrofitTest">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
4. BaseUrl 확인
가져올 JSON은 https://jsonplaceholder.typicode.com/photos 입니다.
[
{
"albumId": 1,
"id": 1,
"title": "accusamus beatae ad facilis cum similique qui sunt",
"url": "https://via.placeholder.com/600/92c952",
"thumbnailUrl": "https://via.placeholder.com/150/92c952"
},
{
"albumId": 1,
"id": 2,
"title": "reprehenderit est deserunt velit ipsam",
"url": "https://via.placeholder.com/600/771796",
"thumbnailUrl": "https://via.placeholder.com/150/771796"
}
...
요청을 위해 dataClass를 model패키지에 정의합니다.
package com.example.retrofittest.model
import com.google.gson.annotations.SerializedName
//데이터 통신을 위한 모델클래스 생성
data class RetroPhoto(
@SerializedName("albumId") var albumId: Int,
@SerializedName("id") var id: Long,
@SerializedName("title") var title: String,
@SerializedName("url") var url: String,
@SerializedName("thumbnailUrl") var thumbnailUrl: String,
){
}
5. Retrofit Instance를 network패키지에 정의
REST API에 요청하기위해 Retrofit.Builder클래스와 baseUrl을 정의한 인스턴스를 사용합니다.
package com.example.retrofittest.network
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.*
//레트로핏 인스턴스 생성
class RetrofitClientInstance {
companion object{
private val BASE_URL: String = "https://jsonplaceholder.typicode.com"
}
fun getRetrofitInstance(): Retrofit{
var retrofit = retrofit2
.Retrofit
.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create()).build()!!
return retrofit
}
}
6. EndPoints설정
service패키지 GetDataService interface를 정의합니다.
package com.example.retrofittest.service
import com.example.retrofittest.model.RetroPhoto
import retrofit2.Call
import retrofit2.http.GET
//엔드포인트 설정
interface GetDataService {
@GET("/photos")
fun getAllPhoto(): Call<List<RetroPhoto>>
}
7. Adapter 정의
RecyclerView에 뿌려주기위해 adapter패키지에 CustomAdapter를 정의합니다.
package com.example.retrofittest.adapter
import android.content.Context
import android.text.Layout
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.retrofittest.R
import com.example.retrofittest.model.RetroPhoto
import com.jakewharton.picasso.OkHttp3Downloader
import com.squareup.picasso.Picasso
class CustomAdapter(var context: Context, var dataList: List<RetroPhoto>) : RecyclerView.Adapter<CustomAdapter.CustomViewHolder>() {
//뷰홀더 생성
inner class CustomViewHolder(val itemView: View) : RecyclerView.ViewHolder(itemView){
var txtTitle : TextView= itemView.findViewById(R.id.title)
var coverImage : ImageView = itemView.findViewById(R.id.coverImage)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val view = layoutInflater.inflate(R.layout.custom_row, parent, false)
return CustomViewHolder(view)
}
override fun onBindViewHolder(holder: CustomViewHolder, position: Int) {
holder.txtTitle.setText(dataList[position].title)
//Picasso라이브러리를 이용하여 ImageView에 간단하게 이미지 로딩
val builder = Picasso.Builder(context)
builder.downloader(OkHttp3Downloader(context))
builder.build().load(dataList[position].thumbnailUrl)
.placeholder((R.drawable.ic_launcher_background))
.error(R.drawable.ic_launcher_background)
.into(holder.coverImage)
}
override fun getItemCount(): Int = dataList.size
}
8. MainActivity
MainActivity에서 요청, 응답수행후 callBack에서 아이템뷰를 만들어줍니다.
package com.example.retrofittest
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.retrofittest.adapter.CustomAdapter
import com.example.retrofittest.model.RetroPhoto
import com.example.retrofittest.service.GetDataService
import com.example.retrofittest.network.RetrofitClientInstance
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//서비스 호출
val service: GetDataService = RetrofitClientInstance().getRetrofitInstance().create(GetDataService::class.java)
//콜백 정의
val call: Call<List<RetroPhoto>> = service.getAllPhoto()
call.enqueue(object: Callback<List<RetroPhoto>>{
override fun onResponse(call: Call<List<RetroPhoto>>, response: Response<List<RetroPhoto>>) {
generateDataList(response.body()!!)
}
override fun onFailure(call: Call<List<RetroPhoto>>, t: Throwable) {
Toast.makeText(applicationContext, "SomeThing went wrong...Plase try later!", Toast.LENGTH_SHORT).show()
}
})
}
private fun generateDataList(photoList: List<RetroPhoto>) {
val recycler: RecyclerView = findViewById(R.id.customRecyclerView)
val layoutManager: RecyclerView.LayoutManager = LinearLayoutManager(applicationContext)
recycler.layoutManager = layoutManager
recycler.adapter = CustomAdapter(this, photoList)
}
}
레이아웃
<?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"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/customRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<ImageView
android:id="@+id/coverImage"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignParentTop="true"
android:scaleType="centerCrop"/>
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/coverImage"
android:layout_marginLeft="16dp"
android:paddingTop="20dp"
android:lines="2"
android:text="title"/>
</RelativeLayout>
</androidx.cardview.widget.CardView>
custom_row.xml
결과
위 사진처럼 정상적으로 뷰가 생성된 것을 확인할 수 있습니다.
참고
Retrofit-A simple Android tutorial
SAM을 사용하는 방법
Retrofit이란?
Author And Source
이 문제에 관하여(Retrofit으로 통신해보기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@appletorch/Retrofit으로-통신해보기저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)