본문 바로가기
혼공노트

안드로이드 맛집 어플 만들기 (4) 북마크 기능 만들기

by 김비거 2024. 6. 19.

* 이 글은 인프런 강의 <[왕초보편] 앱 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>

 

 

저장 버튼 만듦

 

 

 

파이어베이스 실시간 데이터베이스 사용

 

북마크를 위해 실시간 데이터베이스를 이용하여 저장을 한다.

실시간 데이터베이스를 사용하는 방법은 다음 링크에 소개되어 있다.

https://ds3qej.tistory.com/50

 

파이어베이스 인증과 실시간 데이터베이스 사용하기 (2)

* 이 글은 인프런 강의 을 보고 정리한 글입니다. 4. activity_main.xml 리스트뷰와 쓰기 아이콘을 위치시킨다.      5. custom_dialog.xml 쓰기 아이콘을 눌렀을 때 나오는 다이얼로그 창을 만든다.   

ds3qej.tistory.com

 

 

 

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())) 
}

    }
}

 

 

ViewActivity에서 저장버튼을 누르면

 

 

파이어베이스 실시간 데이터베이스에 저장이 된다.

 

 

북마크 불러오기
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

 

 
 

 

댓글