지난번에 파싱한 데이터를 리싸이클러뷰로 화면에 표시를 해보기로했다.

리싸이클러뷰 같은 리스트 모양의 위젯을 선택 위젯이라 부른다고 한다.
선택 위젯은 어댑터 패턴을 사용한다. 어댑터를 이용하여 각각의 아이템을 화면에 나타낸다.
어댑터에서 데이터 관리 기능을 담당하여 데이터를 설정 하고 반환하는 뷰가 하나의 아이템으로 디스플레이 된다.
리스트에 아이템이 1000개라 해도 모든 아이템을 위해 1000개의 뷰 객체가 만들어지지 않는다.
메모리를 효율적으로 사용하기위해 뷰홀더에 뷰객체를 넣어두고 사용자가 스크롤하여 보이지 않는 뷰 객체를 새로 보일 객체로 재활용하는 것이 효율적이다.
<androidx.wear.widget.WearableRecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"/>
리스트를 나타내줄 액티비티에 WearableRecyclerView를 만들어준다.
그리고 어댑터안에 들어갈 데이터를 담아둘 클래스를 만들어준다.
버스정류장 목록을 담을 것이기 때문에 정류장 이름과 id를 가진 클래스를 만들었다.
public class BusStop {
private String nodeName;
private String nodeId;
}
그다음 어댑터클래스도 만들어준다.
public class StopAdapter{
public static class ViewHolder extends RecyclerView.ViewHolder{
TextView textView;
TextView textView2;
public ViewHolder(View itemView){
super(itemView);
textView = itemView.findViewById(R.id.textView);
textView2 = itemView.findViewById(R.id.textView2);
}
public void setItem(BusStop item){
textView.setText(item.getNodeName());
textView2.setText(item.getNodeId());
}
}
}
어댑터클래스 안에 viewholder클래스를 static으로 정의한다.
리스트 형태로 보일 때 각각의 아이템은 뷰로 만들어지며 이 뷰는 뷰홀더에 담아두게된다.
어댑터에서 뷰홀더를 생성하고 미리 생성된 뷰홀더가 있는 경우 이미 만들어진 뷰홀더를 재활용한다.
그리고 어댑터 클래스가 RecyclerView.Adapter<StopAdapter.ViewHolder>를 상속한다.
public class StopAdapter extends RecyclerView.Adapter<StopAdapter.ViewHolder>
그리고 onCreateViewHolder(), onBindViewHolder(), getItemCount() 메서드를 오버라이드 해야한다.
어댑터에서 관리하는 아이템의 개수를 반환한다.
뷰홀더가 새로 만들어지는 시점에 호출되어 각 아이템을 위해 정의한 xml레이아웃을 이용해 뷰객체를 만들어준다.
뷰홀더가 재사용될 때 호출되어 뷰 객체는 기존 것을 그대로 사용하고 데이터만 바꿔준다.
public class StopAdapter extends RecyclerView.Adapter<StopAdapter.ViewHolder>{
ArrayList<BusStop> items = new ArrayList<BusStop>();
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View itemView = inflater.inflate(R.layout.stop_item, parent, false); //인플레이션을 통해 뷰 객체 만들기
//inflate는 xml 로 쓰여있는 View의 정의를 실제 VIew 객체로 만드는 것
return new ViewHolder(itemView);//뷰홀더 객체를 생성하면서 위의 뷰객체 전달하고 뷰홀더 리턴
}
@Override //재활용할 수 있는 뷰홀더 객체, 인덱스
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
BusStop item = items.get(position);
holder.setItem(item); //재활용 가능한 뷰홀더에 setItem으로 뷰 설정?
}
@Override
public int getItemCount() {
return items.size(); //어댑터가 ArrayList안에 들어있는 전체 아이템 개수를 알아야 하므로 아이템개수 리턴
public void addItem(BusStop item){ //Arraylist에 아이템 추가
items.add(item);
}
}
stop_item.xml에서 카드뷰안에 텍스트뷰를 만들어 주었다.
adapter = new StopAdapter(); 어댑터 객체를 만들고 adapter.addItem(new BusStop(id,nm))
으로 아이템을 추가해준다.
그리고 스레드 클래스를 만들어서 파싱작업을 run()에서 해주고 handler를 이용해 어댑터에서 뷰를 설정해주는 것으로 코드를 수정하였다.

기존 결과가 터치하여 스크롤하면 매끄럽지만 rotary input()을 적용하여 베젤을 돌려서 스크롤하면 툭툭 끊기는 느낌이 든다. 카드가 가운데로 오지 않을 때도 있어 스크롤하다보면 위로 움직이는지 아래로 스크롤하고 있는지 헷갈리는 경우도 있었다.

커브 레이아웃을 적용한 결과 카드가 가운데로 오고 멀어질 수록 카드가 작아져서 베젤로 스크롤해도 기존보다 스무스해 보였다.
https://developer.android.com/training/wearables/views/lists#java
https://developer.android.com/reference/androidx/wear/widget/WearableRecyclerView#onTouchEvent(android.view.MotionEvent)
https://github.com/OlegSchwann/WearableRecyclerViewExample/blob/master/app/src/main/java/com/github/olegschwann/wearablerecyclerviewtest2/MainMenuActivity.java
https://ochornmapromise.medium.com/wearable-recyclerview-7f025894c735
https://developer.android.com/training/wearables/user-input/rotary-input#custom-scrolling