이 글은 PC 버전 TISTORY에 최적화 되어있습니다.
서론
ListView 의 작동원리
<ListView 동작원리>
실제 화면에 그려지는 아이템을 ConvertView 라는 배열로 관리하는데, 화면에 보여지는 만큼 Convert View를 생성하고 스크롤시 View를 재활용하기 때문에 성능면으로 우수한 구조이다. ListView의 재활용 View인Convertview는 Adapter의 getView( )를 통해서 관리된다. ListView는 화면에 새로운 아이템을 표시하라 때마다 Adapter의 getView( )를 호출하게 된다. 여기서 getView 메소드는 각 View를 보여줄 때마다 호출되기 때문에 5개의 View를 보여줄 때 무조건 5번의 호출이 이루어지게 된다. ListView는 자원을 재사용 할 때는 null이 아닌 값이 들어오게 되며, null인 경우에는 레이아웃을 inflate한다. ConvertView가 null이 아닌 경우에는 기존의 View 를 재사용하기 때문에 새롭게 View를 inflate 할 필요 없이 데이터만 바꾸는 작업을 진행하면 된다.
개선된 코드는 아래와 같다.
<코드1>
public class XXXAdapter extends ArrayAdapter
{ @Override public View getView(int pos, View convertview ViewGroup parent) { if (convertview == null) { LayoutInflater li = ((LayoutInflater) mCx.getSystemService(Context.LAYOUT_INFLATER_SERVICE)); convertview = li.inflate(R.layout.xxx_item, null); } TextView tx1 = (TextView) convertview.findViewById(R.id.xxxx1); TextView tx2 = (TextView) convertview.findViewById(R.id.xxxx2); ImageView img1 = (ImagView) convertview.findViewById(R.id.yyyy1); Item itm = arraylistItems(pos); tx1.setText(itm.tx1); tx2.setText(itm.tx2); img1.setText(itm.img1); return cv; } }
ViewHolder Pattern
이보다 좀더 개선된 코드가 있는 데 (Google I/O에서 권장됨) 개별 View가 존재하는 경우 View의 setTag / getTag를 이용하여 findViewById를 하지 않는 ViewHolder Pattern 방법이다. ListView에서 아이템이 보여질 때마다 getView( )가 호출된다. 여기서 해당되는 데이터를 View에 표시하기위해 findViewById( )를 통해 해당되는 View를 얻어온 후 데이터를 표시하는 것이 일반적이다. 하지만 아이템 View 구조가 복잡할 경우 매번 findViewById( )를 호출하는 것은 매우 값비싼 작업이기 때문에 매끄러운 스크롤을 방해한다. 아래와 같이 코딩하는 경우 convertview가 없을 경우에만 View를 생성하고 각각의 데이터들을 findViewById를 이용해 찾아주면 되고, convertview가 없는 경우에는 그대로 모든 것을 다 이용하고 데이터의 값만 Setting 해주면 되는 것이다.
개선된 코드는 아래와 같다.
<코드2>
public static class ViewHolder { TextView tx1; TextView tx2; ImageView img1; } public class XXXAdapter extends ArrayAdapter
{ @Override public View getView(int pos, View convertview, ViewGroup parent) { if (convertview == null) { LayoutInflater li = ((LayoutInflater) mCx.getSystemService(Context.LAYOUT_INFLATER_SERVICE)); convertview = li.inflate(R.layout.xxx_item, null); ViewHolder holder = new ViewHolder(); holder.tx1 = (TextView) convertview.findViewById(R.id.xxxx1); holder.tx2 = (TextView) convertview.findViewById(R.id.xxxx2); holder.img1 = (ImagView) convertview.findViewById(R.id.yyyy1); convertview.setTag(holder); } else { holder = (ViewHolder) convertview.getTag(); } Item itm = arraylistItems(pos); holder.tx1.setText(itm.tx1); holder.tx2.setText(itm.tx2); holder.img1.setText(itm.img1); return convertview; } }
'Frontend > Android' 카테고리의 다른 글
[안드로이드] AsyncTask란? (개념 및 사용법) (3) | 2016.07.07 |
---|---|
[안드로이드] runOnUiThread란? (개념과 사용법) (5) | 2016.07.07 |
[안드로이드] Thread, Handler, Looper를 통한 백그라운드 처리 (10) | 2016.07.06 |
[안드로이드] 스레드(Thread) 개념 및 사용법 (5) | 2016.07.06 |
[안드로이드] ANR의 의미와 예방 (2) | 2016.07.05 |
[안드로이드] 리스트뷰의 개념 및 사용법 (1) | 2016.07.05 |