만약 내가 만든 앱화면에서 입력한 글자들을 다른 사람과 함께 보고싶다면..?
-> 웹서버를 만들어야 한다.
-> 웹서버를 만드는 방법도 알아야 하고 운영과정에서 비용이 많이 들 수 있다.
파이어베이스는 데이터의 양이 많지 않다면 무료로 웹서버를 운영할 수 있도록 도와주고
푸시 메시지를 보낼 수 있도록 해준다!
Firebase의 다양한 기능을 알아보려면 여길 참고해보자
영화앱의 한줄평을 작성해서 파이어베이스에 저장하고 리사이클러뷰에 뿌려주는 걸 연습해보자!
1. 안드로이드와 파이어베이스를 연동
www.console.firebase.com 으로 이동해서 새로운 프로젝트를 생성한다. (FirebasePractice)

해당 프로젝트를 클릭하고 왼쪽 메뉴 중 Cloud Firestore메뉴를 눌러 데이터베이스 설정을 한다.
데이터베이스 만들기 -> 테스트모드로 시작 -> 사용설정 클릭
이렇게 하면 데이터베이스 화면에서는 데이터베이스에 저장된 데이터를 보거나 사용량을 살펴 볼 수 있다.
안드로이드 스튜디오로 돌아와
[Tools->Firebase->Realtime Database->Save and retrieve data] -> Connect to Firebase]
->[Add the Realtime Database to your App] 을 누르고 웹 화면 왼쪽 메뉴 중 Realtime Database 클릭!
데이터베이스 만들기-> 사용설정
[규칙] 탭으로 들어가서 .read와 .write속성값을 모두 true로 변경 -> 게시

권한 규칙이 변경되어서 앱에서 읽기 또는 쓰기 가능 -> 데이터베이스에 데이터를 쓰거나 읽을 수 있다!
2. activity_main.xml화면, movie_comment_item.xml 작성하기


3. 리사이클러뷰에 띄워줄 data class Moviecomment.kt
package com.example.firebasepractice
import com.google.firebase.database.Exclude
data class MovieComment(
var objectId: String,
var author:String,
var date:String,
var rating: Long,
var contents:String,
var recommendCount:Long,
var timestamp:Long=0
) {
@Exclude
fun toMap(): HashMap<String, Any> {
val result: HashMap<String, Any> = HashMap()
result["objectId"] = objectId
result["author"] = author
result["date"] = date
result["rating"]=rating
result["contents"]=contents
result["recommendCount"]=recommendCount
result["timestamp"]=timestamp
return result
}
}
toMap() :파이어베이스에 데이터를 저장할 때 Map 자료형으로 저장할 수 있기 때문에 속성들을 HashMap 객체에 넣어서 반환
2. MovieCommentAdapter.kt
class MovieCommentAdapter : RecyclerView.Adapter<MovieCommentAdapter.ViewHolder>() {
var items = ArrayList<MovieComment>()
lateinit var listener: OnMovieCommentClickListener
inner class ViewHolder(private val binding: MovieCommentItemBinding) : RecyclerView.ViewHolder(binding.root) {
init {
itemView.setOnClickListener {
listener?.onItemClick(this, itemView, adapterPosition)
}
}
fun bind(item: MovieComment) {
binding.idTextView.text = item.author
binding.dateTextView.text = item.date
binding.ratingBar.rating = item.rating.toFloat()?:0.0f
binding.contentsTextView.text = item.contents
binding.recommendCountTextView.text = item.recommendCount.toString()
}
}
override fun getItemCount() = items.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding=MovieCommentItemBinding.inflate(LayoutInflater.from(parent.context),parent,false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(items[position])
}
}
3. MainActivity에서 어댑터 달아주기
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var databaseRef:DatabaseReference
private lateinit var adapter:MovieCommentAdapter
var inputDateFormat= SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
var outputDateFormat=SimpleDateFormat("yyyy.MM.dd")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding=ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val layoutManager= LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false)
layoutManager.setReverseLayout(true)
layoutManager.setStackFromEnd(true)
binding.recyclerView.layoutManager=layoutManager
adapter=MovieCommentAdapter()
binding.recyclerView.adapter=adapter
adapter.listener=object:OnMovieCommentClickListener{
override fun onItemClick(holder: MovieCommentAdapter.ViewHolder?, view: View?, position: Int) {
val name=adapter.items[position]
Toast.makeText(applicationContext,"아이템선택됨${name}",Toast.LENGTH_LONG).show()
}
}
}
4. MainActivity에서 Firebase에 한줄평 저장하는 코드 작성
class MainActivity : AppCompatActivity() {
private lateinit var databaseRef:DatabaseReference
override fun onCreate(savedInstanceState: Bundle?) {
binding.saveButton.setOnClickListener { //여기부터 추가
val author=binding.editTextId.text.toString()
val rating=binding.ratingBar.rating.toLong()
val contents=binding.editTextPlot.text.toString()
val recommendCount=0L
saveComment(author,rating,contents,recommendCount)
}
databaseRef= FirebaseDatabase.getInstance("https://fir-practice-acb89-default-rtdb.firebaseio.com/").reference
}
}
- 파이어베이스 데이터베이스: DatabaseReference 자료형으로 참조,
- databaseRef 변수에 firebase데이터베이스를 접근할 수 있는 DatabaseReference 객체를 참조한다.
✔ SaveComment메서드 : 파이어베이스에 데이터 저장
saveComment(author:String, rating: Long, contents:String, recommendCount:Long){
val key:String?=databaseRef.child("comments").push().key
val comment=MovieComment(key.toString(),author,"",rating,contents,recommendCount)
val commentValues:HashMap<String,Any> = comment.toMap()
commentValues["timestamp"]=ServerValue.TIMESTAMP
val childUpdates:MutableMap<String,Any> =HashMap()
childUpdates["/comments/$key"]=commentValues
databaseRef.updateChildren(childUpdates)
//db에서 가져오는 코드
databaseRef.orderByKey().limitToFirst(10).addValueEventListener(object:ValueEventListener{
override fun onDataChange(datasnapshot: DataSnapshot) {
loadCommentList(datasnapshot)
}
override fun onCancelled(databaseError: DatabaseError) {
println("loadItem:onCancelled: ${databaseError.toException()}")
}
})
}
- 파이어베이스 데이터베이스는 객체 단위로 저장하며 계층 구조로 만들어져 있다.
- databaseRef.child 메서드를 통해 하위 객체/속성 참조 , push: 객체추가 -> 객체를 먼저 추가하고 키를 가져오면 키를 객체의 속성으로도 저장 가능
- comment -> MovieComment 객체 -> toMap()메서드로 HashMap 자료형으로 된 객체로 만듦
- updateChildren: DataseReference 객체로 참조하는 정보 업데이트하기 위해 호출
- -> 파라미터는 HashMap 객체 ( 이 객체 안에는 객체의 경로+값이 들어감)
- (객체의 경로를 "/comments/${key}"로 하여 앞에서 만든 객체를 가리키도록 하고 그 값으로 MovieComent객체의 속성들을 HashMap으로 변환했던 객체 commentValues를 넣어줌)
--> Firebase Realtime Database 에 들어가면 데이터가 들어간 것을 볼 수 있다
5. Firebase에 저장된 데이터 가져와서 리사이클러뷰에 띄우기
(saveComment)아래에 다음 코드 추가
databaseRef.orderByKey().limitToFirst(10).addValueEventListener(object:ValueEventListener{
override fun onDataChange(datasnapshot: DataSnapshot) {
loadCommentList(datasnapshot)
}
override fun onCancelled(databaseError: DatabaseError) {
println("loadItem:onCancelled: ${databaseError.toException()}")
}
})
- DataSanpshot 객체: 파이어베이스로부터 조회되는 객체에 접근할 수 있도록 해준다.
loadCommentList 메서드: 조회된 모든 객체들을 리싸이클러뷰에 추가
fun loadCommentList(dataSnapshot: DataSnapshot){
val collectionIterator=dataSnapshot.children.iterator()
if(collectionIterator.hasNext()){
adapter.items.clear()
val comments=collectionIterator.next()
val itemsIterator=comments.children.iterator() //각 comment컬렉션 객체 가져오기 위해
while(itemsIterator.hasNext()){
val currentItem=itemsIterator.next()
val key = currentItem.key
val map=currentItem.getValue() as HashMap<String,Any>
//getValue()를 호출하여 HashMap자료형으로 된 객체 꺼냄
val objectId=map.get("objectId") as String
val author=map.get("author") as String
val contents=map.get("contents") as String
val rating=map.get("rating") as Long
val recommendCount=map.get("recommendCount") as Long
val curDate= Date(map.get("timestamp") as Long)
val curTime=convertCommentTime(curDate)
var commentTime=""
if(curTime!=null){
commentTime=curTime
}
//꺼낸 속성들을 MovieComment객체로 만든 후 어댑터에 추가
adapter.items.add(MovieComment(objectId,author,commentTime,rating,contents,recommendCount))
}
adapter.notifyDataSetChanged() //리싸이클러뷰가 갱신되면서 추가한 아이템 보여줌
}
}

+ 내용을 입력하려고 할때 키보드가 올라오면서 layout의 editText부분이 가려지는 문제가 있었는데
[Android/안드로이드] 키보드로 액티비티 화면 조정 adjustPan
키보드를 올렸을 때 안에 있는 레이아웃이 전체적으로 움직이거나 고정시키고 싶을 때가 있습니다. 이번 포스팅에서는 키보드의 영향에 따라 레이아웃을 조정하는 코드를 작성해보겠습니다.
lakue.tistory.com
이 블로그를 참고해서 해결했다!
'안드로이드' 카테고리의 다른 글
| [Android] BaseActivity/BaseFragment 적용하기 (0) | 2021.11.24 |
|---|---|
| [Android/Kotlin] Fragment에서 ViewPager + Tablayout (0) | 2021.10.11 |
| [Android/Kotlin] 단말 데이터베이스 예제 - 예약 정보 저장 (0) | 2021.08.23 |
| [Android/Kotlin] 단말 데이터베이스 사용하기 (0) | 2021.08.22 |
| [Android/Kotlin] Activity 생명주기 (0) | 2021.08.17 |