컴퓨터/이론: 안드로이드
[2017.09.19] 09. 리스트 뷰 원리 및 성능 향상
heepie
2017. 9. 19. 20:12
리스트 뷰의 원리

리스트 뷰의 원리는 그림과 같이 Data가 Adapter에 등록된 후 Adapter를 통해 ListView에 출력된다.
(리스트 뷰의 개념 - http://heepie.tistory.com/76)
여기서 주목 할 점은 Adapter를 통해 화면에서 사라진 리스트는 다음으로 보여질 리스트로 View가 재활용된다는 것이다.
이렇게 View가 재활용된다는 것에 착안해 리스트 뷰의 성능을 향상 시키는 방법을 알아보자.
문제점1. 끊임없는 객체로드 - 메모리 과부하
(움짤을 계속보면 눈 아파서 접어놨다.)

그림과 같이 listView에서 화면 밖의 아이템을 가져 올 때마다 getView 메소드가 호출되는 것을 확인 할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | class CustomAdapter extends BaseAdapter { // ... // ... // ListView로 나타날 목록을 1개씩 그려주는 메소드 @Override public View getView(int position, View view, ViewGroup viewGroup) { System.out.println("Call getView: " + position); // LayoutInflater는 인자로 입력 받은 xml을 메모리에 로드한다. view = LayoutInflater.from(context).inflate(R.layout.item, null); // 해당 xml에 정의한 TextView를 객체화 TextView textResult = (TextView)view.findViewById(R.id.textResult); // TextView에 데이터 출력 textResult.setText(data.get(position)); return view; } } | cs |
여기서 문제점은 끊임없이 View에 LayoutInflater를 통해 끊임없이 로드되며 속도가 느려지고 메모리 과부하 현상이 발생할 수 있다.
해결책1. View 내부의 값만 변경해 재활용
View 새로 생성해 재활용 |
View 내부 값만 변경해 재활용 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @Override public View getView (int position, View view, ViewGroup vg) { // xml을 메모리에 로드한다. view = LayoutInflater .from(context) .inflate(R.layout.item, null); // 해당 xml에 정의한 TextView를 객체화 TextView textResult = (TextView)view .findViewById(R.id.textResult); // TextView에 데이터 출력 textResult.setText(data.get(position)); return view; } | cs |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | @Override public View getView (int position, View view, ViewGroup vg) { if(view == null) { // xml을 메모리에 로드한다. view = LayoutInflater .from(context) .inflate(R.layout.item, null); } // 해당 xml에 정의한 TextView를 객체화 TextView textResult = (TextView)view .findViewById(R.id.textResult); // TextView에 데이터 출력 textResult.setText(data.get(position)); return view; } | cs |
|
모바일로 문제점 해결 전 후로 App을 실행해 보았을 때 버벅거림이 사라진 것같다... 정말 미세하게 느껴져서 못 느낄 수도 있을 것 같다.
문제점2. 끊임없는 변수, 리스너 등의 선언
위와 같이 개선을 했음에도 불구하고 getView 메소드가 실행 될 때마다 TextView 변수를 선언하고 객체화한다. TextView 변수 하나 설정하는 것이 무슨 문제냐고 말할 수 있지만 리스트 뷰 안에 많은 객체가 들어 갈 수로 더욱 많은 변수를 선언해야 한다.
| @Override public View getView(int position, View view, ViewGroup viewGroup) { // ... TextView textResult = (TextView)view.findViewById(R.id.textResult); // ... return ret; } | cs |
해결책2. Holder 클래스와 Tag 사용해 변수 재활용
호출될 때마다 변수 선언 |
Holder 클래스와 Tag 사용해 변수 재활용 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | @Override public View getView (int position, View view, ViewGroup vg) { if(view == null) { // xml을 메모리에 로드한다. view = LayoutInflater .from(context) .inflate(R.layout.item, null); } // 해당 xml에 정의한 TextView를 객체화 TextView textResult = (TextView)view .findViewById(R.id.textResult); // TextView에 데이터 출력 textResult.setText(data.get(position)); return view; } | cs |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | @Override public View getView (int position, View view, ViewGroup vg) { Holder holder; if(view == null) { // xml을 메모리에 로드한다. view = LayoutInflater .from(context) .inflate(R.layout.item, null); // holder 인스턴스 생성 holder = new Holder(view); // view에 holder 셋팅 view.setTag(holder); } else { // view가 존재하면 holder 셋팅 holder = (Holder)view.getTag(); } // TextView에 데이터 출력 holder.getTextView() .setText(data.get(position)); return view; } | cs |
|
Holder 클래스
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | class Holder { private TextView textView; Holder(View view) { textView = view.findViewById(R.id.textResult); init(); } private void init() { // Holder를 통해 리스너도 설정 가능 textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(view.getContext(), textView.getText() + "", Toast.LENGTH_LONG).show(); } }); } public TextView getTextView() { return textView; } } | cs |
정리

#리스트 뷰 #리스트 뷰 성능 향상 #리스트 뷰 원리 #리스트 뷰 최적화 #리스트 뷰 문제 #리스트뷰