안드로이드 개발에 대해 처음 학습할 때, 굉장히 난감했던 뷰였다.
TextView, EditText, Button 등과 같이 단순한 뷰들은 구현과 활용의 난이도가 낮아 접근이 쉬웠지만,
RecyclerView 는 그렇지 않았다. Adapter 의 개념이 비교적 생소했기 때문이다.
해당 포스트에서는 Data Class 를 이용하여 RecyclerView 에 item 을 동적으로 삽입하는 것에 대해 서술한다.
Data Class
public class Memo {
private String title;
public String getTitle() {
return title;
}
public Memo(String title) {
this.title = title;
}
}
해당 예제에서는 DB 를 사용하지 않지만, 이후 DB 와의 연결이 용이하도록 Data Class 를 생성해준다. 실제로 DB 와 연동하려면 id 값도 할당해주는 것이 좋다.
Adapter Class (My Adapter)
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private ArrayList<Memo> myList = new ArrayList<>();
public MyAdapter(ArrayList<Memo> myList) {
this.myList = myList;
}
@NonNull
@org.jetbrains.annotations.NotNull
@Override
public MyAdapter.ViewHolder onCreateViewHolder(@NonNull @org.jetbrains.annotations.NotNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull @org.jetbrains.annotations.NotNull MyAdapter.ViewHolder holder, int position) {
holder.textView.setText(myList.get(position).getTitle());
}
@Override
public int getItemCount() {
return myList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView textView;
public ViewHolder(@NonNull @org.jetbrains.annotations.NotNull View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.textView);
}
}
}
RecyclerView 를 구현할 때 가장 어려운 부분이 아닌가 싶다. 개발에 대해 처음 배웠을 때는 함수도 많고 코드 자체가 긴 편이라 크게 당황했던 기억이 난다.
먼저, 클래스를 생성하고 RecyclerView.Adapter 를 상속한다.
이후, 만들어 둔 Data Class 를 통해 생성할 객체를 담기 위한 ArrayList 를 초기화한다. 그 뒤, 생성자를 구현해준다.
해당 view 를 return 하기 위해 LayoutInflater 에 대해 정의한다. 이 때, 각 item 의 외관을 구현하기 위한 Layout 을 미리 구현해두어야 한다.
holder 를 통해 item_list 의 textView 를 참조할 수 있다. TextView 외에도 ImageView, Button 모두 가능하며, 심지어는 아이템 내부에 ViewPager 를 삽입하는 경우도 본 적 있다.
마지막으로 getItemCount 와 ViewHolder 에 대해 코딩한다.
getItemCount 의 경우, 함수명을 참 잘 지었다. 매우 직관적인 네이밍이다. ArrayList 가 가진 item 의 갯수를 반환하면 되는데, 마음 편하게 myList.size() 로 처리하면 된다.
ViewHolder 는 데이터를 Data class 를 통해 가공하고 뷰에 담기 전에 잠시 묶어두는 (Hold) 역할을 한다. 생성자를 구현하기 전에 item_list 의 뷰를 초기화 한 뒤, 생성자를 구현하고 생성자 단에서 참조하면 된다.
MainActivity
public class MainActivity extends AppCompatActivity {
EditText editText;
Button button;
RecyclerView recyclerView;
MyAdapter adapter;
ArrayList<Memo> myList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (editText.getText().length() == 0) {
Toast.makeText(MainActivity.this, "입력하세요", Toast.LENGTH_SHORT).show();
} else if (editText.getText().length() > 0) {
Memo memo = new Memo (editText.getText().toString());
myList.add(memo);
editText.setText("");
adapter.notifyDataSetChanged();
}
}
});
}
public void initView() {
editText = findViewById(R.id.editText);
button = findViewById(R.id.button);
recyclerView = findViewById(R.id.recyclerView);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, RecyclerView.VERTICAL, false);
recyclerView.setLayoutManager(linearLayoutManager);
adapter = new MyAdapter(myList);
recyclerView.setAdapter(adapter);
}
}
(initView 함수를 통해 View 참조를 정리해준다. 해당 패턴이 주는 깔끔함이 너무 좋다.)
RecyclerView 에 꼭 필요한 것이 있다. Adapter Class 와 그 객체의 notifyDataSetChanged, LayoutManager.
adapter 를 연결하지 않고 컴파일 할 경우, 앱이 뻗진 않지만, 아무리 데이터를 추가해도 추가되지 않는다.
notifyDataSetChanged 의 경우도 마찬가지다. 앱이 뻗진 않지만, 동적 추가가 불가능하다.
LayoutManager 는 RecyclerView 가 갖는 형태를 결정한다. 해당 예제에서는 LinearLayout 을 사용했지만, Grid 등의 Layout 도 가능하다.
해당 예제에서는 버튼을 눌렀을 때, editText 에 입력된 Text 를 Data Class 를 통해 객체화하여 RecyclerView 에 동적으로 삽입해주고 editText 를 비운다.