* 이 글은 인프런 강의 <[왕초보편] 앱 8개를 만들면서 배우는 안드로이드 코틀린>을 보고 정리한 글입니다.
세부목표 (4)
북마크 기능을 만들기 위해
ViewActivity에 TextView(저장)를 만들고
저장을 눌렀을 때 ContentsModel 데이터 클래스 형태로 파이어베이스의 실시간 데이터베이스에 저장한다.
BookmarkActivity를 생성하여 MainActivity에서 북마크를 눌렀을 때
리사이클러뷰로 저장된 북마크를 보여준다.
북마크 저장하기
activity_view.xml
윗부분에 margin을 주고 저장 TextView를 만든다.
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ViewActivity">
<TextView
android:id="@+id/saveText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="저장"
android:textSize="20sp"
android:layout_margin="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<WebView
android:layout_marginTop="50dp"
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
파이어베이스 실시간 데이터베이스 사용
북마크를 위해 실시간 데이터베이스를 이용하여 저장을 한다.
실시간 데이터베이스를 사용하는 방법은 다음 링크에 소개되어 있다.
MainActivity
putExtra를 통해서 item 클릭이 이루어졌을 때
url, title, imageUrl의 정보를 ViewActivity에 전달하도록 한다.
class MainActivity : AppCompatActivity() {
private val items = mutableListOf<ContentsModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
items.add(
ContentsModel(
"https://www.siksinhot.com/P/349263",
"https://img.siksinhot.com/place/1462946564336361.png?w=307&h=300&c=Y",
"미 피아체"
)
)
...
val recyclerView = findViewById<RecyclerView>(R.id.rv)
val rvAdapter = RVAdapter(baseContext, items)
recyclerView.adapter = rvAdapter
// 어댑터의 itemClick 인터페이스를 구현하여 항목 클릭 시의 동작을 정의
rvAdapter.itemClick = object : RVAdapter.ItemClick {
override fun onClick(view: View, position: Int) {
// 클릭된 항목의 URL, 제목, 이미지 URL을 ViewActivity로 전달하기 위한 Intent 생성
val intent = Intent(baseContext, ViewActivity::class.java)
// 클릭된 항목의 URL을 "url" 키로 Intent에 추가
intent.putExtra("url", items[position].url)
// 클릭된 항목의 제목을 "title" 키로 Intent에 추가
intent.putExtra("title", items[position].titleText)
// 클릭된 항목의 이미지 URL을 "imageUrl" 키로 Intent에 추가
intent.putExtra("imageUrl", items[position].imageUrl)
// ViewActivity를 시작
startActivity(intent)
}
}
recyclerView.layoutManager = GridLayoutManager(this, 2)
}
}
ViewActivity
현재 유저의 UID에 따라 데이터베이스가 저장되도록 한다.
class ViewActivity : AppCompatActivity() {
private lateinit var auth: FirebaseAuth
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_view)
// FirebaseAuth 인스턴스를 초기화
auth = Firebase.auth
val webView = findViewById<WebView>(R.id.webView)
webView.loadUrl(intent.getStringExtra("url").toString())
// Firebase Realtime Database 인스턴스를 초기화하고 bookmark_ref 참조를 가져옴
val database = Firebase.database
val myBookmarkRef = database.getReference("bookmark_ref")
// Intent에서 전달된 데이터(URL, 제목, 이미지 URL)를 가져옴
val url = intent.getStringExtra("url")
val title = intent.getStringExtra("title")
val imageUrl = intent.getStringExtra("imageUrl")
// activity_view 레이아웃에서 saveText TextView를 찾아 saveText 변수에 할당
val saveText = findViewById<TextView>(R.id.saveText)
// saveText에 클릭 리스너를 설정
saveText.setOnClickListener {
// 현재 사용자의 UID를 기준으로 데이터베이스에 북마크 정보를 저장
myBookmarkRef // 데이터베이스의 "bookmark_ref" 참조를 사용
.child(auth.currentUser!!.uid) // 현재 사용자의 UID를 자식 노드로 사용하여 사용자별로 데이터를 구분
.push() // 고유한 키를 생성하여 새로운 자식 노드를 추가
// 생성된 자식 노드에 ContentsModel 객체를 값으로 설정하여 데이터 저장
.setValue(ContentsModel(url.toString(), imageUrl.toString(), title.toString()))
}
}
}
북마크 불러오기
activity_main.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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ff7f00"
tools:context=".MainActivity">
<TextView
android:id="@+id/bookmarkBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="북마크"
android:layout_margin="15dp"
android:textSize="15sp"
android:textStyle="bold"
android:textColor="@color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_marginTop="50dp"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity
북마크 버튼을 눌렀을 때 BookmarkActivity로 넘어가도록 한다.
class MainActivity : AppCompatActivity() {
private val items = mutableListOf<ContentsModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// activity_main 레이아웃에서 bookmarkBtn 버튼을 찾아 bookmarkButton 변수에 할당
val bookmarkButton = findViewById<TextView>(R.id.bookmarkBtn)
// bookmarkButton에 클릭 리스너를 설정
bookmarkButton.setOnClickListener {
// BookmarkActivity로 전환하기 위한 Intent 생성
val intent = Intent(this, BookmarkActivity::class.java)
// BookmarkActivity를 시작
startActivity(intent)
}
...
}
}
activity_bookmark.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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".BookmarkActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
BookmarkActivity
파이어베이스 데이터베이스에서 ContentsModel 형식으로 데이터를 불러온다. (리스트로 저장)
리사이클러뷰 어댑터를 이용하여 contentsModels들을 나타나도록 한다.
이 때 데이터베이스 코드에서 데이터 변경이 되었다는 것을 알려준다. (notifyDataSetChanged)
class BookmarkActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// FirebaseAuth 인스턴스를 초기화
auth = Firebase.auth
// contentsModels 리스트는 ContentsModel 객체를 담는 가변 리스트로, RecyclerView에 표시할 데이터를 포함
private val contentsModels = mutableListOf<ContentsModel>()
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_bookmark)
// Firebase Realtime Database 인스턴스를 초기화
val database = Firebase.database
// "bookmark_ref" 참조를 가져옴
val myBookmarkRef = database.getReference("bookmark_ref")
// activity_bookmark 레이아웃에서 RecyclerView를 찾아 recyclerView 변수에 할당
val recyclerView = findViewById<RecyclerView>(R.id.rv)
// RVAdapter 객체를 생성하여 rvAdapter 변수에 할당, contentsModels 리스트를 어댑터에 전달
val rvAdapter = RVAdapter(baseContext, contentsModels)
// RecyclerView에 어댑터를 설정
recyclerView.adapter = rvAdapter
recyclerView.layoutManager = GridLayoutManager(this, 2)
// 데이터베이스 참조에서 현재 사용자의 UID를 기준으로 데이터 가져오기
myBookmarkRef
.child(auth.currentUser!!.uid.toString())
.addValueEventListener(object : ValueEventListener {
// 데이터가 변경될 때 호출되는 메서드
override fun onDataChange(snapshot: DataSnapshot) {
// snapshot의 자식 데이터를 순회
for (dataModel in snapshot.children) {
Log.d("Datamodel", dataModel.toString())
// 각 자식 데이터를 ContentsModel 객체로 변환하여 리스트에 추가
contentsModels.add(dataModel.getValue(ContentsModel::class.java)!!)
}
// 어댑터에 데이터 변경을 통지하여 RecyclerView를 업데이트
rvAdapter.notifyDataSetChanged()
}
// 데이터베이스 액세스가 취소될 때 호출되는 메서드
override fun onCancelled(error: DatabaseError) {
Log.e("Bookmark", "dbError")
}
})
}
}
정리
파이어베이스 -> 로그인, 이메일/비번, 저장(실시간 데이터베이스)
새로 배운 것: WebView, Glide