도서리뷰 앱 만들기(2) - 도서리뷰저장하기
2022. 12. 23. 17:41ㆍAndroid
- item_book.xml
- 이미지뷰랑 textview를 하나더 추가햇습니다.
- drawble에 backgroud.xml를하나추가해 이미지배경을 다르게해보앗습니다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp">
<ImageView
android:background="@drawable/background_gray_stroke_radius_8"
android:id="@+id/coverImageView"
android:layout_width="100dp"
android:layout_height="100dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/titleTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:ellipsize="end"
android:maxLines="1"
android:text="안드로이드 마스터하기"
android:textColor="@color/black"
android:textSize="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/coverImageView"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/descriptionTextView"
android:layout_width="0dp"
android:layout_height="0dp"
android:ellipsize="end"
android:maxLines="3"
android:textSize="12dp"
android:layout_marginTop="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/titleTextView"
app:layout_constraintTop_toBottomOf="@id/titleTextView" />
</androidx.constraintlayout.widget.ConstraintLayout>
-새로 알게된 용어
ellipsize : width를 넘어갈 경우 textview의 ellipsize로 처리. (글자가 넘어갈경우)
android:ellipsize="end"
android:maxLines="1"
max를 주거나 lines를 주면 내용이 길더라도 ......이렇게표시가된다
모든 Http URL에 대해서 접근 허용
AndroidManifest의 application 태그에서 android:usesCleartextTraffic를 true로 설정하시면 모든 Http 주소에 접근할 수 있습니다.
android:supportsRtl="true"
- Glide 로 이미지 쉽게 불러오기
이미지의 경우 imageview에 표시 할 수 있는데 이때 소스로 자원에 있는 이미지 경로를 넣어주거나
하지만 현재 받아오는것은 이미지의 uri 이기 때문에 이를 쉽게 받아오기 위해 Gide를 사용할수있습니다,
Glide 의존성 주입
implementation 'com.github.bumptech.glide:glide:4.14.2'
annotationProcessor 'com.github.bumptech.glide:compiler:4.14.2'
Glide
.with(binding.coverImageView.context)
.load(bookModel.coverSmallUrl)
.into(binding.coverImageView)
위 사용 예시에서는 with구문을 사용하여 url 을 로드해 오고 이를 into로 어느 이미지 뷰에 뿌려줄지
정하는데 여기에 활용한 바인등을 사용하여 커버 이미지뷰에 뿌려주도록햇습니다.
코드를추가한걸 애뮬레이터를 실행하면
- 도서 목록을 보여주었기때문에 검색어 히스토리 를 저장해보겟다
- 안드로이드 Room DB 사용
먼저 그래들 모듈에 Room을 사용하기위해 의존성을 추가한다.
dependencies {
implementation 'androidx.room:room-runtime:2.4.3'
kapt 'androidx.room:room-compiler:2.4.3'
플러그인에 kotlin -kapt를 추가한다.
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
id 'Kotlin-parcelize'
- 검색 히스토리 dao 구현
package com.example.myapplication.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import com.example.myapplication.model.History
@Dao
interface HistoryDao {
@Query("SELECT * FROM history")
fun getAll() : List<History>
@Insert
fun insertHistory(history: History)
@Query("DELETE FROM history WHERE keyword == :keyword")
fun delete(keyword: String)
}
데이터베이스 테이블 사용할 dao입니다. 검색히스토리를 전부 getall()가져오고,
삽입 삭제하는 쿼리를 정의하고 ,삭제의경우 일치하는 keyword를 지워주도록합니다.
- Review Dao 구현.
package com.example.myapplication.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.example.myapplication.model.Review
@Dao
interface ReviewDao {
@Query("SELECT * FROM review WHERE id == :id")
fun getOneReview (id : Int): Review
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun saveReview(review: Review)
}
- RoomDatabase 만들기
- 데이터베이스를 상속한 앱데이터베이스를 만들어주고 사용하도록햇다.
package com.example.myapplication
import android.content.Context
import androidx.room.Database
import androidx.room.PrimaryKey
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import com.example.myapplication.dao.HistoryDao
import com.example.myapplication.dao.ReviewDao
import com.example.myapplication.model.History
import com.example.myapplication.model.Review
@Database(entities = [History::class, Review::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun historyDao(): HistoryDao
abstract fun ReviewDao(): ReviewDao
}
- 검색리뷰 메인액티비티 만들기
package com.example.myapplication
import android.os.Bundle
import android.os.PersistableBundle
import androidx.appcompat.app.AppCompatActivity
import androidx.room.Room
import androidx.room.util.DBUtil
import com.bumptech.glide.Glide
import com.example.myapplication.databinding.ActivityDetailBinding
import com.example.myapplication.databinding.ActivityMainBinding
import com.example.myapplication.model.Book
import com.example.myapplication.model.Review
class DetailActivity : AppCompatActivity() {
private lateinit var binding: ActivityDetailBinding
private lateinit var db: AppDatabase
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDetailBinding.inflate(layoutInflater)
setContentView(binding.root)
db = Room.databaseBuilder(
applicationContext,
AppDatabase::class.java,
"BookSearchDB"
).build()
val model = intent.getParcelableExtra<Book>("bookModel")
binding.titleTextView.text = model?.title.orEmpty()
binding.descriptionTextView.text = model?.description.orEmpty()
Glide.with(binding.coverImageView.context)
.load(model?.coverSmallUrl.orEmpty())
.into(binding.coverImageView)
Thread {
val review = db.ReviewDao().getOneReview(model?.id?.toInt() ?: 0)
runOnUiThread {
binding.reviewEditTExt.setText(review?.review.orEmpty())
}
}.start()
binding.saveButton.setOnClickListener {
Thread {
db.ReviewDao().saveReview(
Review(
model?.id?.toInt() ?: 0,
binding.reviewEditTExt.text.toString()
)
)
}.start()
}
}
}
- 메인 액티비티 사용
- 메인에서 전역으로 db로 앱데이터베이스를 불러올때 초기화하여 사용하는예시입니다.
- 검색하는 경우 검색한 키워들 저장하는 함수를 실행해 데이터베이스에 히스토리를 삽입
//...
private lateinit var db: AppDatabase
}
//...
db = Room.databaseBuilder(
applicationContext,
AppDatabase::class.java,
"BookSearchDB"
).build()
//...
private fun showHistoryRecyclerView() {
Thread {
val keywords = db.historyDao().getAll().reversed()
runOnUiThread {
binding.historyRecyclerView.isVisible = true
historyAdapter.submitList(keywords.orEmpty())
}
}.start()
binding.historyRecyclerView.isVisible = true
}
private fun hideHistoryRecyclerView() {
binding.historyRecyclerView.isVisible = false
}
private fun saveSearchKeyword(keyword: String) {
Thread {
db.historyDao().insertHistory(History(null, keyword))
}.start()
}
private fun deleteSearhKeyword(keyword: String) {
Thread {
db.historyDao().delete(keyword)
}.start()
}
- 애뮬레이터 실행
'Android' 카테고리의 다른 글
중고거래앱만들기(2) - 리사이클러 뷰 ,홈 화면 구성하기 (0) | 2022.12.31 |
---|---|
중고 거래 앱 만들기 (1) - 프래그먼트 (액티비티처럼 동작하는 뷰) (0) | 2022.12.29 |
도서리뷰 앱 만들기 (1) - Open Api 통해 도서목록 가져오기 (0) | 2022.12.21 |
전자액자 만들기 (2) - 액티비티 생명주기 (0) | 2022.12.16 |
<전자액자 앱만들기>파일 접근 권한과 이미지 업로드 이해와 사용 (0) | 2022.12.13 |