본문 바로가기

소프트웨어/Android/Java/Ndk

Android] LiswView의 성능향상을 위한 HolderPattern

ListView는 특성상 Adapter의 View를 재사용한다. 재사용되는 타이밍도 일정하지 않고, 만약 View에 구성요소가 복잡하거나 많은경우 스크롤이 매우 느려지는 경우가 생길수도있다. BaseAdapter를 상속받은 Adapter Class의 매서드 중 getView()가 재사용에 이용된다. 따라서 getView()에서 재사용을 고려하지 않고 무분별하게 inflate를 시키거나 view들을 생성하면 당연히 성능하락을 유발한다. 그래서 이번 프로젝트에서는 일부 ListView에서 View HolderPattern을 사용하게 되었다.


View HolderPatter이란?

ViewHolder의 객체를 convertView의 값이 null이면(즉, 이전 전달받은 View가 없으면) 최초 생성을 수행해서 불필요하게 View의 요소가 다시 객체생성을 하는것을 방지한다. 이때 ViewHolder객체의 멤버변수로는 getView에서 컨트롤 하고자하는 view 요소(예를들어 textview나 imagview)등을 갖고있다.



public View getView(int position, View convertView, ViewGroup parent) {

WifiListViewHolder viewHolder;

//View v = convertView;

if (convertView == null || convertView.getId() != R.layout.wifi_row_searched) {

Log.d("mstag","wifilistviewholder 첫 생성");

convertView = inflater.inflate(R.layout.wifi_row_searched, null);

viewHolder = new WifiListViewHolder();

viewHolder.searchedSignal0 =(TextView) convertView.findViewById(R.id.searched_signal0);

viewHolder.searchedSignal1 = (TextView) convertView.findViewById(R.id.searched_signal1);

viewHolder.searchedSignal2 = (TextView) convertView.findViewById(R.id.searched_signal2);

viewHolder.searchedSignal3 = (TextView) convertView.findViewById(R.id.searched_signal3);


viewHolder.searchedBusinessName = (TextView)                                             convertView.findViewById(R.id.textviewSearchedBusinessName);

viewHolder.searchedSSID = (TextView) convertView.findViewById(R.id.textviewSearchedSsid);

viewHolder.searchedAddr = (TextView) convertView.findViewById(R.id.textviewSearchedAddr);

viewHolder.searchedLockStateIcon = (ImageView)                                             convertView.findViewById(R.id.imageviewSearchedLockState);


convertView.setTag(viewHolder);

convertView.setId(R.layout.wifi_row_searched);

} else {

Log.d("mstag","convertview가 이미 존재하므로 wifilistviewholder는 getTag로 홀더패턴 적용");

viewHolder = (WifiListViewHolder) convertView.getTag();

}


  

 public class WifiListViewHolder {

TextView searchedSignal0 ;

TextView searchedSignal1 ;

TextView searchedSignal2 ;

TextView searchedSignal3 ;

TextView textviewArr[] ;


TextView searchedBusinessName ;

TextView searchedSSID  ;

TextView searchedAddr ;

ImageView searchedLockStateIcon  ;


}



getView()를 보면 convertView == null을 확인하고 맞을시 convertView에 inflate를 수행한다.

그리고 ViewHolder객체역시 생성한다. 이렇게 생성된 view는 convertView.setTag(HOLDER객체);를 해서 재사용시 convertView의 tag를 get해서 viewHolder를 재생성 하지않고 할당하게 된다.


코드에서 잘 보면 알겠지만, view를 컨트롤하고자 하는 멤버 view들은 모두 ViewHolder가 들고 있기때문에 

ViewHolder객체.멤버View로 컨트롤을 하면 된다.


그 외에 분기문에서 레이아웃을 검사한 이유는 view의 layout이 바뀔때는 새로 생성을 하기 위해서인데, 그다지 신경쓰지 않아도 될 부분같다.