오늘은 인터파크 도서의 정보를 통해 다음 기능을 가진 App을 만들어본다.
- 베스트 셀러 목록을 확인
- 도서 검색
- 리뷰 남기기
API 통신을 위해 저번 포스팅에서 사용했던 Retrofit을 다시한번 사용해본다.
// dependencies에 다음 두줄 추가
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
// 추가로 인터넷 사용 권한도 설정해준다
// Manifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
포스트맨을 사용하여 데이터가 받아와지는지 확인 해보니 잘 넘어온다!
interface BookService {
@GET("/api/search.api?output=json")
fun getBooksByName(
@Query("key") apiKey: String,
@Query("query") keyword: String
): Call<SearchBookDto>
//return형은 Call 반환타입은 SearchBookDto
@GET("/api/bestSeller.api?output=json&categotyId=100")
fun getBestSellerBooks(
@Query("key") apiKey: String
): Call<BestSellerDto>
}
data class Book(
// item 배열의 요소 속 id들
@SerializedName("itemId") val id: Long, //itemId요소를 가져와 id라는 변수에 싱크 해준다
@SerializedName("title") val title: String,
@SerializedName("description") val description: String,
@SerializedName("coverSmallUrl") val coverSmallUrl: String
)
data class SearchBookDto(
// 제일 처음 데이터 요청 시 title 값과 item 목록을 받아온다
@SerializedName("title") val title: String,
@SerializedName("item") val bookList: List<Book> // Book 형태의 List로 받아온다.
)
val retrofit = Retrofit.Builder().baseUrl("https://book.interpark.com")
.addConverterFactory(GsonConverterFactory.create()) //Gson으로 변환
.build()
bookService = retrofit.create(BookService::class.java)
bookService.getBestSellerBooks(getString(R.string.interpark_api_key))
.enqueue(object : Callback<BestSellerDto> {
override fun onResponse(
call: Call<BestSellerDto>,
response: Response<BestSellerDto>
) {
// 성공처리
if (response.isSuccessful.not()) {
return
}
response.body()?.let {
adapter.submitList(it.bookLists)
}
}
override fun onFailure(call: Call<BestSellerDto>, t: Throwable) {
// 실패처리
Log.d(TAG, t.toString())
}
})
}
ROOM 또한 지난 포스팅에서 다룬 적이 있다.
@Entity
data class Review(
@PrimaryKey val id: Int?,
@ColumnInfo(name = "review") val review: String?
)
@Dao
interface ReviewDao {
@Query("SELECT * FROM review WHERE id == :id")
fun getOneReview(id: Int): Review
@Insert(onConflict = OnConflictStrategy.REPLACE) //같은 책의 리뷰가 있으면 새로운 아이로 REPLACE
fun saveReview(review: Review)
}
@Database(entities = [History::class,Review::class],version = 1)
abstract class AppDatabase : RoomDatabase(){
abstract fun historyDao(): HistoryDao
abstract fun reviewDao() : ReviewDao
}
private lateinit var db: AppDatabase
db = Room.databaseBuilder(applicationContext, AppDatabase::class.java, "BookSearchDB")
.build()
// 이미 리뷰가 있다면 불러오기
Thread {
val review = db.reviewDao().getOneReview(model?.id?.toInt() ?: 0)
runOnUiThread {
binding.reviewEditText.setText(review?.review.orEmpty())
}
}.start()
// 리뷰 저장하기 Button 클릭 시
// DB 에 리뷰를 저장
binding.saveButton.setOnClickListener {
Thread {
db.reviewDao().saveReview(
Review(model?.id?.toInt() ?: 0, binding.reviewEditText.text.toString())
)
}.start()
}