RecyclerView.Adapter, ViewHolder(추가)

Posted by ITPangPang
2016. 4. 3. 01:52 안드로이드(android)/Recyclerview


RecyclerView.Adapter, ViewHolder

(추가)


- 이번글에서는 이전글에서 끝내려고 했는데 몇가지 알아볼 것이 

  생겨서 몇가지 더 테스트를 하였다.


- 이전글에서 못끝낸 부분

  1. onCreateViewHolder에서 최초로 생성되는 View갯수가 

     화면에 보이는갯수 +3인지에 대한 여부와

  2. onBindViewHolder에서 생성되는 Holder가 어떻게 재활용되는지를 알아보면 될 것 같습니다.



- 먼저 1번에 관한 궁금증은 화면에 22개의 Item이 보이면 22+3개의 View가 생성되고, 

  11개의 Item이 보이면 11+3개의 View가 생성되는것을 확인하여서 무조건 화면에 보이는 Item갯수+3개의 View가 생성되는

  것인가 그렇다면 나머지 Item들은 어떤 View에 뿌려주는가

  화면에 들어오는 Item수의 변경시켜보면서 테스트한 결과 항상 Item수+3개의 View가 생성되었습니다.

  


그렇다면 나머지 Item들은 어떤 View에 담는지 알아보겠습니다


1. 원활한 테스트를 위해 Custom.xml의 TextView의 TextSize를 90sp로 변경하였습니다

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<TextView
android:id="@+id/tv"
android:textColor="#000000"
android:textSize="90sp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>


2. 원활한 테스트를 위해 CountAdapter.java도 변경

public class CountAdapter extends RecyclerView.Adapter<CountAdapter.MyViewHolder>
{
Context mContext;
List<Integer> items;
int i = 0;
final static String TAG = "ITPANGPANG";


public CountAdapter(Context c, List<Integer> items, int i)
{
this.mContext = c;
this.items = items;
this.i = i;
}
@Override
public CountAdapter.MyViewHolder onCreateViewHolder(ViewGroup viewGroup, int i)
{
Log.d(TAG,"========onCreateViewHolder========");
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.recyclerview_custom, viewGroup, false);
Log.d(TAG, "View v=>" + v);
return new MyViewHolder(v);
}

@Override
public void onBindViewHolder(CountAdapter.MyViewHolder myViewHolder, int position)
{
Log.d(TAG, "========onBindViewHolder========");
final Integer item = items.get(position);
//myViewHolder.tv.setText(""+item);
}


@Override
public int getItemCount()
{
return this.items.size();
}

public class MyViewHolder extends RecyclerView.ViewHolder
{
TextView tv;
public MyViewHolder(View itemView)
{
super(itemView);
Log.d(TAG, "========MyViewHolder========");
tv = (TextView) itemView.findViewById(R.id.tv);
Log.d(TAG,"itemView"+itemView.toString().substring(31,36));
tv.setText("" + itemView.toString().substring(31,36));
}
}
}

첫번째 변경코드는 onBindViewHolder에서 TextView에 숫자1씩 증가하는 코드를 주석처리

두번째 변경코드는 MyViewHolder class에서 TextView에 itemView.toString().subString()을 setText


OnCreateViewHolder에서 MyViewholder로 view를 return해주므로 

MyViewHolder에서 같은 View를 처리하므로 여기서 Log를 대신 찍어줬다

또한 원활한 테스트를 위해 기존에 View값이 android.widg~{42b9d510~찍히던것을

알아보기 쉽게 바뀌는 부분만 표시하기 위해 공통부분은 substring으로 다 잘라냈다.

또한 화면에 1,2,3,4로 찍히는 부분을 사용하는 View가 찍히도록 변경하였다.


3. 앱을 실행후 버튼을 대충 40번정도 눌러보고 로그캣을 지운후에 다시 버튼 한번을 더 눌러본다


화면에 5개의 Item이 보이므로 View는 5+3=8개가 생성될 것이다.


일단 버튼 한번 눌렀을때(스크롤 내리기전)

로그캣에 눈에 보이는 5개의 View가 생성되었다.


폰에 찍힌걸 보니 로그캣과 동일한 View의 이름이 찍혀있다.


이번에는 스크롤을 제일 하단으로 내려보면



역시 에상대로 +3개의 View가 더 생성되어 8개가 생성되었다.


다시 폰화면을 가장 위로 올려봤다 



이상한점이 아까는 View순서가 0acd0, 0c2e8,0d900,0ef18,10530이었는데


지금은 변경되있었다. 한번더 스크롤을 끝까지 내렸다가 다시 맨위로 올려봤다.



결과는 또 바뀌어있었다. 천천히 50개 정도의 Item을 내리면서 봤더니


로그캣에 찍힌 8개의 View 이름에서 벗어나진 않았다. 


결국 8개의 View를 재활용해서 사용한다는것이다.



여기까지만 테스트해봐도 화면에보이는 Item갯수+3개의 View와 


그 View를 재활용 한다는것을 알았으니 그만하려 했으나 


분명히 스크롤이 움직일때는 onBindViewHolder만 호출되는 줄 알았는데


onBindViewHolder에서 setText해주는 부분이 없는데 왜 TextView내용이 변하는지 궁금하다.


코드를 하나 추가해봤다.


public class MyViewHolder extends RecyclerView.ViewHolder
{
TextView tv;
public MyViewHolder(View itemView)
{
super(itemView);
m++;
Log.d(TAG, "========MyViewHolder========");
tv = (TextView) itemView.findViewById(R.id.tv);
Log.d(TAG,"itemView=>"+itemView.toString().substring(31,36));
tv.setText(m+"." + itemView.toString().substring(31,36));
}
}

 

Int m을 추가해서 앞에 TextView에 숫자.가 붙도록 했다


그리고 실행해서 버튼을 40번 정도 눌러봤다.



예상했던 대로 앞에 숫자가 붙어서 잘 뜬다.


스크롤을 한번 내려봤다. 그랬더니?




아래 8까지는 예상 대로 떳는데 그 아래부터 신기한 현상이 일어났다


1 5 2 7 4 3 6 5 8 7번 순서대로 Text가 박혔다..


그리고 숫자 옆에 붙은 View를 확인해보니 일치했다.


앞에 숫자 붙여보길 잘했다는 생각이 들었다..


일단 처음에는 View+3(8.de8d8)까지는 setText를 찍어주고


그 아래부터는 랜덤으로 사용했던 View와 초기에 박혔던 Text까지 그대로


복사해서 재활용해서 화면에 뿌려주는것을 확인하였다.


이전글을 떠올려보면 호출되는 순서가

OnCreateViewHolder->MyViewHolder->onBindViewHolder였다.


MyViewHolder에서 초기셋팅만 해주고 결국은 onBindViewHolder에서

setText해주는 값이 최종적으로 화면에 출력되는 값이었다.



setText해주는 값이 최종적으로 화면에 출력되는 값이었다.



- 다음은 onBindViewHolder에서 생성되는 Holder가 어떻게 재활용 되는지


- 이것도 뭐 결론만 말하면 비슷했습니다 (Item이 많을때)화면에 보이는 갯수+3개의 Holder가 생성되었고

   View처럼 규칙적으로 Item마다 정해져있는 것이 아니라 랜덤으로 생성되는 것을 확인했습니다.

   테스트중 좀 특이한게 있었으나.. 이건 왜 그런지 알려고 파고들면 오히려 독이 될거 같아서..


- 이것으로 추가적으로 테스트를 끝내봤고,, 여태까지 이것을 왜 했는가 하면..


-  나중에 좀 더 복잡하게 활용해야 할 때 대비해서 어떤 값을 어떻게 이용해야 할 지 미리 준비를 해둔것이고..


   나중에 특정 위치를 뽑거나 UI변경시 단순하게 View나 ViewHolder의 값을 다이렉트로 사용하면 안된다는 것과

   결국 믿을것은 position 밖에 없다는 것이다.(단순하게 보자면 position이 절대 위치이고)

   나중에 좀더 응용해서 쓰자면 item나 holder에 담긴 내용을 뽑아서 그 위치를 파악해서 사용해야 할 것이다..


- 이것으로 이번글을 마쳐야 할 것 같다.. Recycler에 대해 100% 아는상태에서 글을 쓰는것이 아니라서

   틀린것도 많을것 같고.. 뻘짓 하는것도 많아보이지만.. 어쨋든 해서 나쁠건 없다고 보니 만족한다..


- 음 다음글은 RecyclerView 클릭(선택)이나 아니면 notify에 대해 쓸 것 같다.

  (지금 개인적으로 SmoothScrollToPosition에 대해 재밋어서 연구중인데 얼른 끝내고 글을 썼으면 좋겠다)


'안드로이드(android) > Recyclerview' 카테고리의 다른 글

RecyclerView(Item Click) 2탄  (8) 2016.04.07
RecyclerView(Item Click) 1탄  (0) 2016.04.06
RecyclerView.Adapter, ViewHolder  (3) 2016.04.02
RecyclerView 기본  (2) 2016.04.02
RecyclerView  (0) 2016.04.01