(Android) Firebase RealTime DB 사용하기 (2) 사용하기
1. 앱에 실시간 데이터베이스 추가
앱 수준 build.gradle
implementation 'com.google.firebase:firebase-database:16.1.0'
2. 데이터베이스 선언 및 초기화
//선언
DatabaseReference mDatabase;
//초기화
mDatabase = FirebaseDatabase.getInstance().getReference();
3. 쓰기
(int) age, (String) fullName, (String) favoriteFoods, (Long) nowTime 4가지 정보를 예시로 해보겠습니다.
1) Json 유형 - 단순 쓰기
Key 값이 PA-LAB인 데이터를 찾아서 자식에 추가해줍니다. 없다면, Key를 생성해줍니다.
//MainActivity
Map<String, Object> map = new HashMap<>();
map.put("age", 21);
map.put("fullName","paran laboratory");
map.put("favoriteFoods","chicken");
map.put("nowTime",System.currentTimeMillis());
mDatabase.child("PA-LAB").setValue(map);
2) 맞춤 class 유형 - 커스텀 사용
info class를 만들어줍니다. getter라고하는데 다음과 같이 직접 만들어주면 됩니다.
//info
@IgnoreExtraProperties
public class info {
public int age;
public String fullName;
public String favoriteFoods;
public long nowTime;
public info() {
// Default constructor
}
public info(int age, String fullName, String favoriteFoods, long nowTime) {
this.age = age;
this.fullName = fullName;
this.favoriteFoods = favoriteFoods;
this.nowTime = nowTime;
}
}
//MainActivity
info info_palab = new info(21,"paran laboratory","chicken",System.currentTimeMillis());
mDatabase.child("PA-LAB").setValue(info_palab);
1번과 2번의 결과는 같습니다. 하지만, 2번 방식을 사용해야합니다. 왜냐하면, 더 효율적이니까요.
데이터를 여러개 쓰거나, 읽을 때 엄청난 차이를 보입니다.
Key는 PA-LAB 입니다.
반복의 예시입니다.
info info_palab = new info(21,"paran laboratory","chicken",System.currentTimeMillis());
info info_nolab = new info(21,"norang laboratory","pizza",System.currentTimeMillis()*2);
info info_cholab = new info(21,"chorock laboratory","hamburger",System.currentTimeMillis()*3);
mDatabase.child("PA-LAB").setValue(info_palab);
mDatabase.child("NO-LAB").setValue(info_nolab);
mDatabase.child("CHO-LAB").setValue(info_cholab);
Key는 각각 CHO-LAB, NO-LAB, PA-LAB 입니다.
3) 목록 쓰기 - 데이터 구조화
push() 는 목록을 만들어주는데, 랜덤한 문자열을 Key로 할당합니다.
push 후에 데이터를 넣어주어야 목록이 만들어집니다.
mDatabase.push().setValue(info_palab);
Key는 LgqrkBbir0HEV_A3zxc 입니다.
3. 읽기
데이터베이스에 리스너를 달아주어야 한다. 리스너를 선언하고, 초기화하고, 달아주면된다.
데이터베이스에 리스너를 달아주면됩니다. 데이터가 변경될 시 자동으로 호출되며, 2가지 종류가 존재합니다.
중요한 점은 데이터베이스에 리스너는 꼭 하나만 달려있어야합니다. 중첩 사용시 중첩 작동하여 문제가 발생합니다.
add로 리스너를 달아주고, remove로 리스너를 해제해야합니다. 해제하기 싫으면, 한번만 실행되게 달아줄 수도 있습니다. ValueEventListener의 경우 addListenerForSingleValueEvent()를 해주면 remove할 필요없이 한번만 실행되고 끝납니다.
1) ValueEventListener
변경사항을 한번에 처리한다. 삭제, 추가, 목록 추가 등 하위(자식) 데이터들이 변경될 시 onDataChange가 호출된다.
//선언
ValueEventListener mValueEventListener;
//초기화
ValueEventListener mValueEventListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
String key = postSnapshot.getKey();
info info_each = postSnapshot.getValue(info.class);
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
};
//사용
mDatabase.addValueEventListener(mValueEventListener);
//삭제
mDatabase.removeEventListener(mValueEventListener);
아래 예시를 들어보겠습니다.
info info_palab = new info(21,"paran laboratory","chicken",System.currentTimeMillis());
info info_nolab = new info(21,"norang laboratory","pizza",System.currentTimeMillis()*2);
info info_cholab = new info(21,"chorock laboratory","hamburger",System.currentTimeMillis()*3);
mDatabase.child("LAB-LIST").push().setValue(info_palab);
mDatabase.child("LAB-LIST").push().setValue(info_nolab);
mDatabase.child("LAB-LIST").push().setValue(info_cholab);
ValueEventListener mValueEventListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
String key = postSnapshot.getKey();
info info_each = postSnapshot.getValue(info.class);
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
};
mDatabase.child("LAB-LIST").addValueEventListener(mValueEventListener);
for문은 총 3번 돕니다. 리스너를 LAB-LIST에 달았기때문에, 그 하위 데이터 Key의 데이터들에 접근합니다.
key에는 LgrJctfpcOVGefVUqRT, LgrJctqyCIgf8Gqv0TQ, LgrJctqyCIgf8Gqv0TR 이 담기고,
info_each에는 info_palab, info_nolab, info_cholab 이 담깁니다.
2) ChildEventListener
두 리스너는 모두 비슷하게 동작하며, ChildEventListener은 조금 더 구체적으로 작동합니다. 데이터의 변경 종류에 따라
onChildAdded(), onChildChanged(), onChildRemoved(), onChildMoved()가 호출됩니다.
자세한 코드는 설명하지 않겠습니다. 대신 FireBase 하위 이벤트 수신 대기 를 참고하세요!
info_each에는 info클래스가 객체로 담기는데, info클래스를 만들고, getter을 만들면 자동으로 데이터를 매칭시켜줍니다.
만약 class를 만들지 않는다면, 데이터를 가져오는데 아주 복잡해질 것입니다.
4. 왜 사용할까, Log
사용방법은 끝났습니다! 이걸 왜 굳이 사용할까라는 생각이 들어서, 찾아본 내용을 정리해보았습니다.
서버는 큰 비용이 들 수도 있습니다. 작은 서버는 무료로 제공해주는 곳이 많은데 복잡합니다. 데이터를 처리하는게 어렵습니다. Firebase는 우리에게 서버를 제공해주고 관리까지 해줍니다. 앱을 서버 테스트를 하고 싶은데 아마존에서 서버를 구해서, 적용시키기는 복잡하지만 Firebase는 아주 간단합니다. 그리고 또 일정 용량 무료기 때문에 테스트로 아주 좋고, 용량이 넘으면 자동으로 확장시켜주기 때문에 간편합니다. 그 정도 크기가 된다면, 일정 수익이 발생할 것입니다. 왜냐면 10GB나 주거든요..!
생각보다 쉽게 정리된 블로그들이 없어서 처음에 엄청 헤맸습니다..최대한 쉽게 설명하고, 막혔던 부분들을 정리했습니다.