//테이블이라고 생각하고, 테이블에 들어갈 속성값을 넣기
//파이어베이스는 RDBMS와 다르기 때문에 테이블이라는 개념이 없음. 원래는 키값이라고 부름
public class animal {
String name; //동물 이름
String kind; //동물 종류
public animal(){} //이건 기본적으로 쓰더라구요.
//get, set 함수는 커스텀 리스트 뷰를 사용하시는 분들과.. 필요하신 분만 작성하시면 좋습니다.
public String getname() {
return name;
}
public void setname(String name) {
this.name = name;
}
public String getkind() {
return kind;
}
public void setkind(String kind) {
this.kind = kind;
}
//값을 추가할때 쓰는 함수, MainActivity에서 addanimal함수에서 사용할 것임.
public animal(String name, String kind){
this.name = name;
this.kind = kind;
}
}
데이터베이스 저장
이제 메인엑티비티에서 데이터베이스를 연동해줌 //전역변수로정의
// 파이어베이스 데이터베이스 연동
private final FirebaseDatabase database = FirebaseDatabase.getInstance();
//DatabaseReference는 데이터베이스의 특정 위치로 연결하는 거라고 생각하면 된다.
//현재 연결은 데이터베이스에만 딱 연결해놓고
//키값(테이블 또는 속성)의 위치 까지는 들어가지는 않은 모습이다.
private final DatabaseReference databaseReference = database.getReference();
public void addanimal(String name, String kind) {
Log.d("jinsoltest","애니멀함수 ");
//여기에서 직접 변수를 만들어서 값을 직접 넣는것도 가능합니다.
// ex) 갓 태어난 동물만 입력해서 int age=1; 등을 넣는 경우
//animal.java에서 선언했던 함수.
animal animal = new animal(name,kind);
//push()는 값을 넣을때 상위 키값을 랜덤으로 설정해 주는 함수입니다.
//채팅기능을 만들때 사용하면 좋습니다.
databaseReference.child("zoo").push().setValue(animal);
//Toast.makeText(context,"db전송 :"+edit1.getText().toString()+" , "+edit2.getText().toString(),Toast.LENGTH_SHORT).show();
}
데이터베이스 읽기
public void ReadAnimal(){
FirebaseDatabase.getInstance().getReference().addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Log.d("jinsoltest", "ValueEventListener : " + snapshot.getValue());
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
}
activity_news.xml에 id를 부여하였고 width,height 는 match로 설정함
<row_news.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="wrap_content"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!--뉴스 이미지를 넣을 것-->
<ImageView
android:id="@+id/ImageView_news"
android:layout_width="match_parent"
android:layout_height="45dp"
android:src="@drawable/ic_launcher_background"></ImageView>
<!-- 뉴스의 제목을 넣을 공간 -->
<TextView
android:id="@+id/TextView_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hello, this is example of RecycleView"
android:layout_alignBottom="@+id/ImageView_news"
android:textSize="20dp"
android:background="#77ff88aa"
></TextView>
</RelativeLayout>
<!--뉴스의 내용 일부를 적을 공간-->
<TextView
android:id="@+id/TextView_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Contents part"
android:textSize="15dp"
android:ellipsize="end"
></TextView>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
recyclerview에 들어가는 아이템뷰 각항목의 디자인을
이미지,텍스트뷰(제목),텍스트뷰(내용)으로 설정해주었음
<NewsActivity.class> matched with activity_news.xml
package com.example.news1124;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class NewsActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager layoutManager;
/* 리스트의 각 객체들에 들어갈 데이터들 / DB로부터 또는 사용자로부터 받아올 수 있다 */
private String[] myDataset = {"첫 번째 뉴스의 제목 ","두 번째 뉴스의 제목","세 번째 뉴스의 제목"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* matching with activity_news*/
setContentView(R.layout.activity_news);
/* activity_news.xml에서 RecyclerView 가져옴 */
recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
recyclerView.setHasFixedSize(true);
// use a linear layout manager
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
/* Adapter를 연결 !
Adapter를 사용해서 리스트의 각 항목들을 효과적으로 관리 */
// specify an adapter (see also next example)
mAdapter = new MyAdapter(myDataset); // Adapter생성자를 사용 해당 생성자는 Myadapter.class에서 확인
recyclerView.setAdapter(mAdapter);
}
}
setContentview(R.layout.activity_news) 를 통해 레이아웃을 activity_news.xml과 매칭시켜줌
recyclerview 를 findview를통해 연결해주고
recyclerview.setHasFixedSize()에 true값을 줌으로써 RecyclerView의 레이아웃 크기는 변경되지 않음
layoutManager = new LinearLayoutManager(this); 레이아웃매니저 생성
recyclerview.setLayoutmanager(layoutmanger)을통해 recyclerview에 레이아웃매니저 지정
madapter = new myadapter(mydataset);
recyclerview.setadapter()을 통해 recyclerview에 어뎁터 지정
MyAdapter.class
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private String[] mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
/* 리스트 내의 각 항목들을 관리하는 ViewHolder class*/
public static class MyViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView TextView_title;
public TextView TextView_content;
public ImageView ImageView_news;
/* 가져오는 layout에서 id값을 통해 해당 Component를 가져와 변수에 저장 */
public MyViewHolder(View v) {
super(v);
TextView_title = v.findViewById(R.id.TextView_title);
TextView_content = v.findViewById(R.id.TextView_content);
ImageView_news = v.findViewById(R.id.ImageView_news);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
/* NewsActivity에서 Adapter와 매칭시 사용하는 사용자이다
이 때 NewsActivity의 데이터들이 데이터배열을 통해 전달되어진다
*/
public MyAdapter(String[] myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
@Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
/* 리스트의 각 항목에 입혀줄 디자인을 생성한다 즉, create a new view
setContentView(R.layout.xxx) 처럼 xml 매칭, 하지만 RecycleView의 특정 부분만 변경시킬 때는
효율성을 위해 inflate함수를 사용
사용할 xml(row_news)의 최상위 layout을 이용
* */
androidx.constraintlayout.widget.ConstraintLayout v
= (androidx.constraintlayout.widget.ConstraintLayout) LayoutInflater.from(parent.getContext())
.inflate(R.layout.row_news, parent, false);
MyViewHolder vh = new MyViewHolder(v); /* row_news에서 components를 가져와 MyViewHolder객체의 변수들에 저장된다*/
return vh;
}
// Replace the contents of a view (값 대입)
@Override
/* MyAdapter.class와 매칭되어있는 row_news.xml에 있는 TextView_title 컴포넌트에 값 SET */
public void onBindViewHolder(MyViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
// TextView_title component에 값을 지정한다 NewsActivity.class에서 넘어온 mDataset에 있는 데이터
holder.TextView_title.setText(mDataset[position]);
}
// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
return mDataset.length;
}
}
이미지 , 버튼보다 중요하고 더욱 많이등장하며 모든앱에 존재하고 리스트는 data를 담고있으므로 매우중요하다.
이 리스트를 구현하는방법은 여러가지가 있는데
기본적으로 ListView를 사용하는 방법이있다. 하지만 리스트뷰는 api level 1부터 존재했으며
listview의 재사용성이 떨어지며 메모리성능 부분에 많은 악영향을 미칠수있을수도 있기때문에
약간 상위버전? 업그레이드 버전으로 Recyclerview가 롤리팝(5.0)버전이 발표되엇다.
개인적으로 위의 그림이 RecyclerView를 이해하는 데 도움이 많이 되었다.
그림을 이해하자면, ListView와는 다르게 RecyclerView는 이름에서 알 수 있듯이 재활용이 가능한 뷰이다. 무엇을 재활용 할까? 오른 쪽 그림을 보자. 파란색 라인 한 개가 채팅방 리스트 한 개라고 가정하자. 전체 채팅방 리스트는 100개가 훌쩍 넘을 수가 있다. 그러나 정작 화면에 보여지는 채팅방 목록은 한 번에 10개 조차 되지 않는다.
매번 사용자가 아래로 스크롤 할 때 마다 맨 위에 위치한 뷰 객체가 새로 삭제되고, 아랫 부분에서 새로 나타날 채팅방 뷰 객체를 새로 생성하면 결국 100개의 뷰 객체가 삭제되고 생성되는 것일 뿐만 아니라, 스크롤을 위아래로 왔다 갔다 하면 수 백개의 뷰 객체가 새로 생성되고 삭제됨을 반복한다.
리사이클러 뷰는 사용자가 아래로 스크롤 한다고 가정했을 때, 맨 위에 존재해서 이제 곧 사라질 뷰 객체를 삭제 하지않고 아랫쪽에서 새로 나타나날 파란색 뷰 위치로 객체를 이동시킨다. 즉 뷰 객체 자체를 재사용 하는 것인데, 중요한 점은 뷰 객체를 재사용 할 뿐이지 뷰 객체가 담고 있는 데이터(채팅방 이름)는 새로 갱신된다는 것이다. 어쨋거나 뷰 객체를 새로 생성하지는 않으므로 효율적인 것이다.
결과적으로 보자면, 맨 처음 화면에 보여질 10개 정도의 뷰 객체만을 만들고, 실제 데이터가 100개든 1000개든 원래 만들어 놓은 10개의 객체만 계속 해서 재사용 하는 것이다.